vigiles 2.0.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/.claude/settings.json +46 -0
- package/.claude/settings.local.json +8 -0
- package/.claude-plugin/hooks/post-edit.sh +34 -0
- package/.claude-plugin/hooks/pre-edit.sh +40 -0
- package/.claude-plugin/hooks/session-start.sh +38 -0
- package/.claude-plugin/marketplace.json +14 -0
- package/.claude-plugin/plugin.json +47 -0
- package/.github/workflows/ci.yml +81 -0
- package/.prettierignore +1 -0
- package/.vigiles/generated.d.ts +205 -0
- package/CLAUDE.md +95 -0
- package/CLAUDE.md.spec.ts +142 -0
- package/CONTRIBUTING.md +121 -0
- package/LICENSE +21 -0
- package/README.md +377 -0
- package/action.yml +25 -0
- package/dist/action.d.ts +7 -0
- package/dist/action.d.ts.map +1 -0
- package/dist/action.js +180 -0
- package/dist/action.js.map +1 -0
- package/dist/cli.d.ts +12 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +1267 -0
- package/dist/cli.js.map +1 -0
- package/dist/cli.test.d.ts +2 -0
- package/dist/cli.test.d.ts.map +1 -0
- package/dist/cli.test.js +650 -0
- package/dist/cli.test.js.map +1 -0
- package/dist/compile.d.ts +101 -0
- package/dist/compile.d.ts.map +1 -0
- package/dist/compile.js +503 -0
- package/dist/compile.js.map +1 -0
- package/dist/evolve.d.ts +132 -0
- package/dist/evolve.d.ts.map +1 -0
- package/dist/evolve.js +599 -0
- package/dist/evolve.js.map +1 -0
- package/dist/freshness.d.ts +67 -0
- package/dist/freshness.d.ts.map +1 -0
- package/dist/freshness.js +244 -0
- package/dist/freshness.js.map +1 -0
- package/dist/freshness.test.d.ts +2 -0
- package/dist/freshness.test.d.ts.map +1 -0
- package/dist/freshness.test.js +356 -0
- package/dist/freshness.test.js.map +1 -0
- package/dist/generate-types.d.ts +34 -0
- package/dist/generate-types.d.ts.map +1 -0
- package/dist/generate-types.js +381 -0
- package/dist/generate-types.js.map +1 -0
- package/dist/inline.d.ts +58 -0
- package/dist/inline.d.ts.map +1 -0
- package/dist/inline.js +142 -0
- package/dist/inline.js.map +1 -0
- package/dist/inline.test.d.ts +5 -0
- package/dist/inline.test.d.ts.map +1 -0
- package/dist/inline.test.js +152 -0
- package/dist/inline.test.js.map +1 -0
- package/dist/linters.d.ts +38 -0
- package/dist/linters.d.ts.map +1 -0
- package/dist/linters.js +588 -0
- package/dist/linters.js.map +1 -0
- package/dist/proofs.d.ts +272 -0
- package/dist/proofs.d.ts.map +1 -0
- package/dist/proofs.js +622 -0
- package/dist/proofs.js.map +1 -0
- package/dist/proofs.test.d.ts +9 -0
- package/dist/proofs.test.d.ts.map +1 -0
- package/dist/proofs.test.js +952 -0
- package/dist/proofs.test.js.map +1 -0
- package/dist/spec.d.ts +258 -0
- package/dist/spec.d.ts.map +1 -0
- package/dist/spec.js +113 -0
- package/dist/spec.js.map +1 -0
- package/dist/spec.test.d.ts +2 -0
- package/dist/spec.test.d.ts.map +1 -0
- package/dist/spec.test.js +1222 -0
- package/dist/spec.test.js.map +1 -0
- package/dist/types.d.ts +101 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +3 -0
- package/dist/types.js.map +1 -0
- package/dist/validate.d.ts +10 -0
- package/dist/validate.d.ts.map +1 -0
- package/dist/validate.js +286 -0
- package/dist/validate.js.map +1 -0
- package/dist/validate.test.d.ts +2 -0
- package/dist/validate.test.d.ts.map +1 -0
- package/dist/validate.test.js +531 -0
- package/dist/validate.test.js.map +1 -0
- package/docs/agent-setup.md +85 -0
- package/docs/agent-workflows.md +103 -0
- package/docs/comparison.md +71 -0
- package/docs/freshness.md +124 -0
- package/docs/inline-mode.md +119 -0
- package/docs/linter-support.md +166 -0
- package/docs/spec-format.md +194 -0
- package/eslint.config.mjs +79 -0
- package/examples/CLAUDE.md +54 -0
- package/examples/CLAUDE.md.spec.ts +65 -0
- package/examples/SKILL.md +50 -0
- package/examples/SKILL.md.spec.ts +57 -0
- package/fixtures/example-project/CLAUDE.md +11 -0
- package/fixtures/example-project/package.json +9 -0
- package/fixtures/example-project/src/index.ts +3 -0
- package/fixtures/example-project/src/utils.test.ts +2 -0
- package/fixtures/example-project/src/utils.ts +3 -0
- package/logo.png +0 -0
- package/package.json +42 -0
- package/research/adoption-strategy.md +111 -0
- package/research/agent-integration.md +145 -0
- package/research/ai-code-quality.md +197 -0
- package/research/code-search-for-agents.md +313 -0
- package/research/competitive-landscape.md +163 -0
- package/research/doc-freshness.md +516 -0
- package/research/executable-specs.md +368 -0
- package/research/feature-ideas.md +464 -0
- package/research/formal-proofs-for-agents.md +338 -0
- package/research/fp-for-agent-harness.md +150 -0
- package/research/fp-for-deterministic-ai.md +131 -0
- package/research/self-evolving-specs.md +298 -0
- package/schemas/claude-md-strict.yml +18 -0
- package/schemas/claude-md.yml +6 -0
- package/schemas/skill-strict.yml +12 -0
- package/schemas/skill.yml +5 -0
- package/skills/audit-feedback-loop/SKILL.md +76 -0
- package/skills/edit-spec/SKILL.md +131 -0
- package/skills/enforce-rules-format/SKILL.md +71 -0
- package/skills/generate-logo/SKILL.md +102 -0
- package/skills/generate-rule/SKILL.md +90 -0
- package/skills/linter-docs/clippy.md +241 -0
- package/skills/linter-docs/eslint.md +384 -0
- package/skills/linter-docs/pylint.md +288 -0
- package/skills/linter-docs/rubocop.md +277 -0
- package/skills/linter-docs/ruff.md +187 -0
- package/skills/linter-docs/stylelint.md +247 -0
- package/skills/migrate-to-spec/SKILL.md +124 -0
- package/skills/pr-to-lint-rule/SKILL.md +97 -0
- package/skills/strengthen/SKILL.md +168 -0
- package/src/action.ts +214 -0
- package/src/cli.test.ts +914 -0
- package/src/cli.ts +1631 -0
- package/src/compile.ts +691 -0
- package/src/evolve.ts +781 -0
- package/src/freshness.test.ts +449 -0
- package/src/freshness.ts +299 -0
- package/src/generate-types.ts +448 -0
- package/src/inline.test.ts +206 -0
- package/src/inline.ts +164 -0
- package/src/linters.ts +739 -0
- package/src/proofs.test.ts +1314 -0
- package/src/proofs.ts +849 -0
- package/src/spec.test.ts +1471 -0
- package/src/spec.ts +427 -0
- package/src/types.ts +117 -0
- package/src/validate.test.ts +701 -0
- package/src/validate.ts +381 -0
- package/tsconfig.json +23 -0
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
{
|
|
2
|
+
"hooks": {
|
|
3
|
+
"SessionStart": [
|
|
4
|
+
{
|
|
5
|
+
"matcher": "startup|compact",
|
|
6
|
+
"hooks": [
|
|
7
|
+
{
|
|
8
|
+
"type": "command",
|
|
9
|
+
"command": "npm install && npm run build && pip install ruff pylint && gem install rubocop 2>/dev/null; true"
|
|
10
|
+
}
|
|
11
|
+
]
|
|
12
|
+
}
|
|
13
|
+
],
|
|
14
|
+
"PostToolUse": [
|
|
15
|
+
{
|
|
16
|
+
"matcher": "Edit|Write",
|
|
17
|
+
"hooks": [
|
|
18
|
+
{
|
|
19
|
+
"type": "command",
|
|
20
|
+
"command": "FILE=$(cat | jq -r '.tool_input.file_path // empty') && case \"$(basename \"$FILE\")\" in eslint.config.*|.eslintrc*|package.json|pyproject.toml|Cargo.toml) npx vigiles generate-types 2>&1 || true ;; esac && case \"$FILE\" in *.spec.ts) npx vigiles compile 2>&1 || true ;; esac"
|
|
21
|
+
}
|
|
22
|
+
]
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
"matcher": "Edit|Write",
|
|
26
|
+
"hooks": [
|
|
27
|
+
{
|
|
28
|
+
"type": "command",
|
|
29
|
+
"command": "npx prettier --check ."
|
|
30
|
+
}
|
|
31
|
+
]
|
|
32
|
+
}
|
|
33
|
+
],
|
|
34
|
+
"PreToolUse": [
|
|
35
|
+
{
|
|
36
|
+
"matcher": "Edit|Write",
|
|
37
|
+
"hooks": [
|
|
38
|
+
{
|
|
39
|
+
"type": "command",
|
|
40
|
+
"command": "FILE=$(cat | jq -r '.tool_input.file_path // empty') && case \"$FILE\" in *.md) [ -f \"$FILE\" ] && head -1 \"$FILE\" | grep -q 'vigiles:sha256:' && { SPEC=$(head -1 \"$FILE\" | sed -n 's/.*compiled from \\(.*\\) -->/\\1/p'); echo \"BLOCKED: Edit $SPEC instead.\" >&2; exit 2; } ;; esac; exit 0"
|
|
41
|
+
}
|
|
42
|
+
]
|
|
43
|
+
}
|
|
44
|
+
]
|
|
45
|
+
}
|
|
46
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# PostToolUse hook — keep generated types and compiled specs fresh.
|
|
3
|
+
#
|
|
4
|
+
# Reads stdin JSON from Claude Code to determine which file was edited,
|
|
5
|
+
# then conditionally runs generate-types or compile.
|
|
6
|
+
|
|
7
|
+
set -euo pipefail
|
|
8
|
+
|
|
9
|
+
INPUT=$(cat)
|
|
10
|
+
FILE=$(echo "$INPUT" | jq -r '.tool_input.file_path // empty' 2>/dev/null)
|
|
11
|
+
|
|
12
|
+
if [ -z "$FILE" ]; then
|
|
13
|
+
exit 0
|
|
14
|
+
fi
|
|
15
|
+
|
|
16
|
+
BASENAME=$(basename "$FILE")
|
|
17
|
+
|
|
18
|
+
# Linter config or package.json changed → regenerate types
|
|
19
|
+
case "$BASENAME" in
|
|
20
|
+
eslint.config.*|.eslintrc*|.stylelintrc*|.rubocop.yml|pyproject.toml|Cargo.toml|package.json)
|
|
21
|
+
if command -v npx &>/dev/null && [ -f "package.json" ]; then
|
|
22
|
+
npx vigiles generate-types 2>&1 || true
|
|
23
|
+
fi
|
|
24
|
+
;;
|
|
25
|
+
esac
|
|
26
|
+
|
|
27
|
+
# Spec file changed → recompile
|
|
28
|
+
case "$FILE" in
|
|
29
|
+
*.spec.ts)
|
|
30
|
+
if command -v npx &>/dev/null && [ -f "package.json" ]; then
|
|
31
|
+
npx vigiles compile 2>&1 || true
|
|
32
|
+
fi
|
|
33
|
+
;;
|
|
34
|
+
esac
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# PreToolUse hook — redirect edits from compiled files to their specs.
|
|
3
|
+
#
|
|
4
|
+
# If a file has a vigiles hash comment, it's a build artifact.
|
|
5
|
+
# Exit 2 = block the tool call in Claude Code.
|
|
6
|
+
# The message tells the agent exactly what to do instead.
|
|
7
|
+
|
|
8
|
+
set -euo pipefail
|
|
9
|
+
|
|
10
|
+
INPUT=$(cat)
|
|
11
|
+
FILE=$(echo "$INPUT" | jq -r '.tool_input.file_path // empty' 2>/dev/null)
|
|
12
|
+
|
|
13
|
+
if [ -z "$FILE" ]; then
|
|
14
|
+
exit 0
|
|
15
|
+
fi
|
|
16
|
+
|
|
17
|
+
# Only check .md files
|
|
18
|
+
case "$FILE" in
|
|
19
|
+
*.md) ;;
|
|
20
|
+
*) exit 0 ;;
|
|
21
|
+
esac
|
|
22
|
+
|
|
23
|
+
# Check if the file exists and has a vigiles hash
|
|
24
|
+
if [ -f "$FILE" ] && head -1 "$FILE" | grep -q "<!-- vigiles:sha256:"; then
|
|
25
|
+
SPEC=$(head -1 "$FILE" | sed -n 's/.*compiled from \(.*\) -->/\1/p')
|
|
26
|
+
SPEC_FILE="${SPEC:-$(basename "$FILE").spec.ts}"
|
|
27
|
+
|
|
28
|
+
cat >&2 <<MSG
|
|
29
|
+
BLOCKED: ${FILE} is a compiled build artifact — do not edit it directly.
|
|
30
|
+
|
|
31
|
+
Instead:
|
|
32
|
+
1. Read ${SPEC_FILE} to understand the spec structure
|
|
33
|
+
2. Edit ${SPEC_FILE} to make your changes (add/modify rules, sections, keyFiles, commands)
|
|
34
|
+
3. Run: npx vigiles compile
|
|
35
|
+
4. The compiled ${FILE} will be regenerated automatically
|
|
36
|
+
|
|
37
|
+
Use the edit-spec skill if you need guidance on the spec format.
|
|
38
|
+
MSG
|
|
39
|
+
exit 2
|
|
40
|
+
fi
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# SessionStart hook — inject a one-line vigiles audit summary into
|
|
3
|
+
# Claude's context at session start and after compaction.
|
|
4
|
+
#
|
|
5
|
+
# Uses `vigiles audit --summary` which is designed for this: it
|
|
6
|
+
# silences all per-stage output and prints a single line like
|
|
7
|
+
# vigiles: 3 stale / 2 validation errors / 1 duplicate
|
|
8
|
+
# (or "vigiles: clean") so the injection costs a handful of tokens.
|
|
9
|
+
#
|
|
10
|
+
# Hook runs on the `startup` and `compact` matchers — the latter is
|
|
11
|
+
# effectively free on token budget because it fires every time
|
|
12
|
+
# context is compacted, so the agent re-notices drift without any
|
|
13
|
+
# manual command.
|
|
14
|
+
|
|
15
|
+
set -euo pipefail
|
|
16
|
+
|
|
17
|
+
# Only run in projects that actually use vigiles — otherwise stay silent.
|
|
18
|
+
if [ ! -f "package.json" ]; then
|
|
19
|
+
exit 0
|
|
20
|
+
fi
|
|
21
|
+
if ! grep -q '"vigiles"' package.json 2>/dev/null; then
|
|
22
|
+
exit 0
|
|
23
|
+
fi
|
|
24
|
+
|
|
25
|
+
# Prefer local install, fall back to npx.
|
|
26
|
+
if command -v npx &>/dev/null; then
|
|
27
|
+
SUMMARY=$(npx --no-install vigiles audit --summary 2>/dev/null || true)
|
|
28
|
+
else
|
|
29
|
+
exit 0
|
|
30
|
+
fi
|
|
31
|
+
|
|
32
|
+
if [ -z "$SUMMARY" ]; then
|
|
33
|
+
exit 0
|
|
34
|
+
fi
|
|
35
|
+
|
|
36
|
+
# Inject the summary line as hook output. Claude Code prepends hook
|
|
37
|
+
# stdout to the session context for SessionStart hooks.
|
|
38
|
+
echo "$SUMMARY"
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "vigiles",
|
|
3
|
+
"metadata": {
|
|
4
|
+
"description": "Tools for AI-assisted development feedback loops"
|
|
5
|
+
},
|
|
6
|
+
"plugins": [
|
|
7
|
+
{
|
|
8
|
+
"name": "vigiles",
|
|
9
|
+
"source": "./",
|
|
10
|
+
"description": "Validate CLAUDE.md, audit feedback loops, and generate lint rules from PR comments",
|
|
11
|
+
"version": "1.0.0"
|
|
12
|
+
}
|
|
13
|
+
]
|
|
14
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "vigiles",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Validate CLAUDE.md, audit feedback loops, and generate lint rules from PR comments",
|
|
5
|
+
"author": {
|
|
6
|
+
"name": "zernie"
|
|
7
|
+
},
|
|
8
|
+
"repository": "https://github.com/zernie/vigiles",
|
|
9
|
+
"license": "MIT",
|
|
10
|
+
"keywords": ["linting", "claude-md", "feedback-loops", "code-review"],
|
|
11
|
+
"skills": "./skills/",
|
|
12
|
+
"hooks": {
|
|
13
|
+
"PreToolUse": [
|
|
14
|
+
{
|
|
15
|
+
"matcher": "Edit|Write",
|
|
16
|
+
"hooks": [
|
|
17
|
+
{
|
|
18
|
+
"type": "command",
|
|
19
|
+
"command": "bash ${CLAUDE_PLUGIN_ROOT}/hooks/pre-edit.sh"
|
|
20
|
+
}
|
|
21
|
+
]
|
|
22
|
+
}
|
|
23
|
+
],
|
|
24
|
+
"PostToolUse": [
|
|
25
|
+
{
|
|
26
|
+
"matcher": "Edit|Write",
|
|
27
|
+
"hooks": [
|
|
28
|
+
{
|
|
29
|
+
"type": "command",
|
|
30
|
+
"command": "bash ${CLAUDE_PLUGIN_ROOT}/hooks/post-edit.sh"
|
|
31
|
+
}
|
|
32
|
+
]
|
|
33
|
+
}
|
|
34
|
+
],
|
|
35
|
+
"SessionStart": [
|
|
36
|
+
{
|
|
37
|
+
"matcher": "startup|compact",
|
|
38
|
+
"hooks": [
|
|
39
|
+
{
|
|
40
|
+
"type": "command",
|
|
41
|
+
"command": "bash ${CLAUDE_PLUGIN_ROOT}/hooks/session-start.sh"
|
|
42
|
+
}
|
|
43
|
+
]
|
|
44
|
+
}
|
|
45
|
+
]
|
|
46
|
+
}
|
|
47
|
+
}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main]
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
test:
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
steps:
|
|
13
|
+
- uses: actions/checkout@v4
|
|
14
|
+
|
|
15
|
+
- uses: actions/setup-node@v4
|
|
16
|
+
with:
|
|
17
|
+
node-version: "20"
|
|
18
|
+
cache: "npm"
|
|
19
|
+
|
|
20
|
+
- uses: actions/setup-python@v5
|
|
21
|
+
with:
|
|
22
|
+
python-version: "3.x"
|
|
23
|
+
|
|
24
|
+
- uses: ruby/setup-ruby@v1
|
|
25
|
+
with:
|
|
26
|
+
ruby-version: "3.3"
|
|
27
|
+
|
|
28
|
+
- name: Cache pip packages
|
|
29
|
+
uses: actions/cache@v4
|
|
30
|
+
with:
|
|
31
|
+
path: ~/.cache/pip
|
|
32
|
+
key: pip-${{ runner.os }}-ruff-pylint
|
|
33
|
+
|
|
34
|
+
- name: Cache gem packages
|
|
35
|
+
uses: actions/cache@v4
|
|
36
|
+
with:
|
|
37
|
+
path: ~/.local/share/gem
|
|
38
|
+
key: gem-${{ runner.os }}-rubocop
|
|
39
|
+
|
|
40
|
+
- run: npm ci
|
|
41
|
+
|
|
42
|
+
- name: Install linter CLIs for tests
|
|
43
|
+
run: |
|
|
44
|
+
pip install ruff pylint
|
|
45
|
+
gem install rubocop
|
|
46
|
+
rustup component add clippy
|
|
47
|
+
|
|
48
|
+
- name: Build
|
|
49
|
+
run: npm run build
|
|
50
|
+
|
|
51
|
+
- name: Run tests
|
|
52
|
+
run: npm test
|
|
53
|
+
|
|
54
|
+
- name: Type check
|
|
55
|
+
run: npx tsc --noEmit
|
|
56
|
+
|
|
57
|
+
- name: Check generated types compile
|
|
58
|
+
run: node dist/cli.js generate-types && npx tsc --noEmit
|
|
59
|
+
|
|
60
|
+
- name: Lint
|
|
61
|
+
run: npm run lint
|
|
62
|
+
|
|
63
|
+
- name: Check formatting
|
|
64
|
+
run: npm run fmt:check
|
|
65
|
+
|
|
66
|
+
check:
|
|
67
|
+
runs-on: ubuntu-latest
|
|
68
|
+
steps:
|
|
69
|
+
- uses: actions/checkout@v4
|
|
70
|
+
|
|
71
|
+
- uses: actions/setup-node@v4
|
|
72
|
+
with:
|
|
73
|
+
node-version: "20"
|
|
74
|
+
|
|
75
|
+
- run: npm ci
|
|
76
|
+
|
|
77
|
+
- name: Build
|
|
78
|
+
run: npm run build
|
|
79
|
+
|
|
80
|
+
- name: Audit compiled files
|
|
81
|
+
run: node dist/cli.js audit
|
package/.prettierignore
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
.vigiles/generated.d.ts
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Auto-generated by `vigiles generate-types`.
|
|
3
|
+
* DO NOT EDIT — re-run `vigiles generate-types` to update.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
declare module "vigiles/generated" {
|
|
7
|
+
|
|
8
|
+
/** 64 enabled eslint rules (via flat config). */
|
|
9
|
+
export type EslintRule =
|
|
10
|
+
| "constructor-super"
|
|
11
|
+
| "for-direction"
|
|
12
|
+
| "getter-return"
|
|
13
|
+
| "no-async-promise-executor"
|
|
14
|
+
| "no-case-declarations"
|
|
15
|
+
| "no-class-assign"
|
|
16
|
+
| "no-compare-neg-zero"
|
|
17
|
+
| "no-cond-assign"
|
|
18
|
+
| "no-const-assign"
|
|
19
|
+
| "no-constant-binary-expression"
|
|
20
|
+
| "no-constant-condition"
|
|
21
|
+
| "no-control-regex"
|
|
22
|
+
| "no-debugger"
|
|
23
|
+
| "no-delete-var"
|
|
24
|
+
| "no-dupe-args"
|
|
25
|
+
| "no-dupe-class-members"
|
|
26
|
+
| "no-dupe-else-if"
|
|
27
|
+
| "no-dupe-keys"
|
|
28
|
+
| "no-duplicate-case"
|
|
29
|
+
| "no-empty"
|
|
30
|
+
| "no-empty-character-class"
|
|
31
|
+
| "no-empty-pattern"
|
|
32
|
+
| "no-empty-static-block"
|
|
33
|
+
| "no-ex-assign"
|
|
34
|
+
| "no-extra-boolean-cast"
|
|
35
|
+
| "no-fallthrough"
|
|
36
|
+
| "no-func-assign"
|
|
37
|
+
| "no-global-assign"
|
|
38
|
+
| "no-import-assign"
|
|
39
|
+
| "no-invalid-regexp"
|
|
40
|
+
| "no-irregular-whitespace"
|
|
41
|
+
| "no-loss-of-precision"
|
|
42
|
+
| "no-misleading-character-class"
|
|
43
|
+
| "no-new-native-nonconstructor"
|
|
44
|
+
| "no-nonoctal-decimal-escape"
|
|
45
|
+
| "no-obj-calls"
|
|
46
|
+
| "no-octal"
|
|
47
|
+
| "no-prototype-builtins"
|
|
48
|
+
| "no-redeclare"
|
|
49
|
+
| "no-regex-spaces"
|
|
50
|
+
| "no-self-assign"
|
|
51
|
+
| "no-setter-return"
|
|
52
|
+
| "no-shadow-restricted-names"
|
|
53
|
+
| "no-sparse-arrays"
|
|
54
|
+
| "no-this-before-super"
|
|
55
|
+
| "no-unassigned-vars"
|
|
56
|
+
| "no-undef"
|
|
57
|
+
| "no-unexpected-multiline"
|
|
58
|
+
| "no-unreachable"
|
|
59
|
+
| "no-unsafe-finally"
|
|
60
|
+
| "no-unsafe-negation"
|
|
61
|
+
| "no-unsafe-optional-chaining"
|
|
62
|
+
| "no-unused-labels"
|
|
63
|
+
| "no-unused-private-class-members"
|
|
64
|
+
| "no-unused-vars"
|
|
65
|
+
| "no-useless-assignment"
|
|
66
|
+
| "no-useless-backreference"
|
|
67
|
+
| "no-useless-catch"
|
|
68
|
+
| "no-useless-escape"
|
|
69
|
+
| "no-with"
|
|
70
|
+
| "preserve-caught-error"
|
|
71
|
+
| "require-yield"
|
|
72
|
+
| "use-isnan"
|
|
73
|
+
| "valid-typeof";
|
|
74
|
+
|
|
75
|
+
/** All enabled linter rules across all detected linters. */
|
|
76
|
+
export type LinterRule = EslintRule;
|
|
77
|
+
|
|
78
|
+
/** 5 npm scripts from package.json. */
|
|
79
|
+
export type NpmScript =
|
|
80
|
+
| "build"
|
|
81
|
+
| "test"
|
|
82
|
+
| "lint"
|
|
83
|
+
| "fmt"
|
|
84
|
+
| "fmt:check";
|
|
85
|
+
|
|
86
|
+
/** 18 project files. */
|
|
87
|
+
export type ProjectFile =
|
|
88
|
+
| "src/action.ts"
|
|
89
|
+
| "src/cli.test.ts"
|
|
90
|
+
| "src/cli.ts"
|
|
91
|
+
| "src/compile.ts"
|
|
92
|
+
| "src/evolve.ts"
|
|
93
|
+
| "src/freshness.test.ts"
|
|
94
|
+
| "src/freshness.ts"
|
|
95
|
+
| "src/generate-types.ts"
|
|
96
|
+
| "src/inline.test.ts"
|
|
97
|
+
| "src/inline.ts"
|
|
98
|
+
| "src/linters.ts"
|
|
99
|
+
| "src/proofs.test.ts"
|
|
100
|
+
| "src/proofs.ts"
|
|
101
|
+
| "src/spec.test.ts"
|
|
102
|
+
| "src/spec.ts"
|
|
103
|
+
| "src/types.ts"
|
|
104
|
+
| "src/validate.test.ts"
|
|
105
|
+
| "src/validate.ts";
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
declare module "vigiles/spec" {
|
|
109
|
+
interface KnownLinterRules {
|
|
110
|
+
"eslint":
|
|
111
|
+
| "constructor-super"
|
|
112
|
+
| "for-direction"
|
|
113
|
+
| "getter-return"
|
|
114
|
+
| "no-async-promise-executor"
|
|
115
|
+
| "no-case-declarations"
|
|
116
|
+
| "no-class-assign"
|
|
117
|
+
| "no-compare-neg-zero"
|
|
118
|
+
| "no-cond-assign"
|
|
119
|
+
| "no-const-assign"
|
|
120
|
+
| "no-constant-binary-expression"
|
|
121
|
+
| "no-constant-condition"
|
|
122
|
+
| "no-control-regex"
|
|
123
|
+
| "no-debugger"
|
|
124
|
+
| "no-delete-var"
|
|
125
|
+
| "no-dupe-args"
|
|
126
|
+
| "no-dupe-class-members"
|
|
127
|
+
| "no-dupe-else-if"
|
|
128
|
+
| "no-dupe-keys"
|
|
129
|
+
| "no-duplicate-case"
|
|
130
|
+
| "no-empty"
|
|
131
|
+
| "no-empty-character-class"
|
|
132
|
+
| "no-empty-pattern"
|
|
133
|
+
| "no-empty-static-block"
|
|
134
|
+
| "no-ex-assign"
|
|
135
|
+
| "no-extra-boolean-cast"
|
|
136
|
+
| "no-fallthrough"
|
|
137
|
+
| "no-func-assign"
|
|
138
|
+
| "no-global-assign"
|
|
139
|
+
| "no-import-assign"
|
|
140
|
+
| "no-invalid-regexp"
|
|
141
|
+
| "no-irregular-whitespace"
|
|
142
|
+
| "no-loss-of-precision"
|
|
143
|
+
| "no-misleading-character-class"
|
|
144
|
+
| "no-new-native-nonconstructor"
|
|
145
|
+
| "no-nonoctal-decimal-escape"
|
|
146
|
+
| "no-obj-calls"
|
|
147
|
+
| "no-octal"
|
|
148
|
+
| "no-prototype-builtins"
|
|
149
|
+
| "no-redeclare"
|
|
150
|
+
| "no-regex-spaces"
|
|
151
|
+
| "no-self-assign"
|
|
152
|
+
| "no-setter-return"
|
|
153
|
+
| "no-shadow-restricted-names"
|
|
154
|
+
| "no-sparse-arrays"
|
|
155
|
+
| "no-this-before-super"
|
|
156
|
+
| "no-unassigned-vars"
|
|
157
|
+
| "no-undef"
|
|
158
|
+
| "no-unexpected-multiline"
|
|
159
|
+
| "no-unreachable"
|
|
160
|
+
| "no-unsafe-finally"
|
|
161
|
+
| "no-unsafe-negation"
|
|
162
|
+
| "no-unsafe-optional-chaining"
|
|
163
|
+
| "no-unused-labels"
|
|
164
|
+
| "no-unused-private-class-members"
|
|
165
|
+
| "no-unused-vars"
|
|
166
|
+
| "no-useless-assignment"
|
|
167
|
+
| "no-useless-backreference"
|
|
168
|
+
| "no-useless-catch"
|
|
169
|
+
| "no-useless-escape"
|
|
170
|
+
| "no-with"
|
|
171
|
+
| "preserve-caught-error"
|
|
172
|
+
| "require-yield"
|
|
173
|
+
| "use-isnan"
|
|
174
|
+
| "valid-typeof";
|
|
175
|
+
}
|
|
176
|
+
interface KnownProjectFiles {
|
|
177
|
+
files:
|
|
178
|
+
| "src/action.ts"
|
|
179
|
+
| "src/cli.test.ts"
|
|
180
|
+
| "src/cli.ts"
|
|
181
|
+
| "src/compile.ts"
|
|
182
|
+
| "src/evolve.ts"
|
|
183
|
+
| "src/freshness.test.ts"
|
|
184
|
+
| "src/freshness.ts"
|
|
185
|
+
| "src/generate-types.ts"
|
|
186
|
+
| "src/inline.test.ts"
|
|
187
|
+
| "src/inline.ts"
|
|
188
|
+
| "src/linters.ts"
|
|
189
|
+
| "src/proofs.test.ts"
|
|
190
|
+
| "src/proofs.ts"
|
|
191
|
+
| "src/spec.test.ts"
|
|
192
|
+
| "src/spec.ts"
|
|
193
|
+
| "src/types.ts"
|
|
194
|
+
| "src/validate.test.ts"
|
|
195
|
+
| "src/validate.ts";
|
|
196
|
+
}
|
|
197
|
+
interface KnownNpmScripts {
|
|
198
|
+
scripts:
|
|
199
|
+
| "build"
|
|
200
|
+
| "test"
|
|
201
|
+
| "lint"
|
|
202
|
+
| "fmt"
|
|
203
|
+
| "fmt:check";
|
|
204
|
+
}
|
|
205
|
+
}
|
package/CLAUDE.md
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
<!-- vigiles:sha256:2a0c0efd642c787a compiled from CLAUDE.md.spec.ts -->
|
|
2
|
+
|
|
3
|
+
# CLAUDE.md
|
|
4
|
+
|
|
5
|
+
## Positioning
|
|
6
|
+
|
|
7
|
+
vigiles compiles `.spec.ts` files to instruction files (CLAUDE.md, AGENTS.md, or any markdown target). The spec is the source of truth. The markdown is a build artifact. Nobody else does this — other tools lint markdown after the fact. vigiles eliminates the problem at the source.
|
|
8
|
+
|
|
9
|
+
The linter cross-referencing engine is the core moat: `enforce("@typescript-eslint/no-floating-promises")` verifies the rule exists AND is enabled in your linter config. Same for ESLint, Ruff, Clippy, Pylint, RuboCop, and Stylelint. No other tool resolves rules against 6 linter APIs.
|
|
10
|
+
|
|
11
|
+
`generate-types` is the second moat: scans all 6 linter APIs, package.json, and project files to emit a `.d.ts` with type unions. The TS compiler then PROVES references are valid at authoring time — typos become type errors, not runtime surprises.
|
|
12
|
+
|
|
13
|
+
vigiles does NOT do architectural linting. Use ast-grep, Dependency Cruiser, Steiger, or eslint-plugin-boundaries for that. vigiles can reference their rules via `enforce()`.
|
|
14
|
+
|
|
15
|
+
## Architecture
|
|
16
|
+
|
|
17
|
+
Two rule types in specs:
|
|
18
|
+
|
|
19
|
+
- `enforce()` — delegated to external tool (linter, ast-grep, dependency-cruiser). vigiles verifies the rule exists and is enabled.
|
|
20
|
+
- `guidance()` — prose only, compiles to `**Guidance only**` in markdown.
|
|
21
|
+
|
|
22
|
+
Architectural linting (file pairing, import boundaries, AST patterns) belongs in external tools — reference them via `enforce()`.
|
|
23
|
+
|
|
24
|
+
Template literal types ensure linter names (`eslint/`, `ruff/`, etc.) are type-safe. Branded types (`VerifiedPath`, `VerifiedCmd`, `VerifiedRef`) distinguish verified references from raw strings.
|
|
25
|
+
|
|
26
|
+
Compilation: spec.ts → compiler reads spec, validates references (file paths via existsSync, npm scripts via package.json, linter rules via linter APIs), generates markdown with SHA-256 integrity hash.
|
|
27
|
+
|
|
28
|
+
Core modules: `src/spec.ts` (types + builders), `src/compile.ts` (compiler), `src/linters.ts` (6-linter cross-referencing engine), `src/generate-types.ts` (type generator), `src/proofs.ts` (proof algorithms for self-evolving specs), `src/evolve.ts` (evolution engine).
|
|
29
|
+
|
|
30
|
+
## Key Files
|
|
31
|
+
|
|
32
|
+
- `src/spec.ts` — Type system and builder functions (enforce, guidance, claude, skill, file, cmd, ref)
|
|
33
|
+
- `src/compile.ts` — Compiler: spec → markdown with SHA-256 hash, linter verification, reference validation
|
|
34
|
+
- `src/linters.ts` — Linter cross-referencing engine (ESLint, Stylelint, Ruff, Clippy, Pylint, RuboCop)
|
|
35
|
+
- `src/generate-types.ts` — Type generator: scans linters/package.json/filesystem → emits .d.ts
|
|
36
|
+
- `src/cli.ts` — CLI: init, compile, audit (3 primary commands + generate-types plumbing)
|
|
37
|
+
- `src/inline.ts` — Inline-mode parser: `<!-- vigiles:enforce ... -->` comments in markdown for gradual adoption
|
|
38
|
+
- `src/action.ts` — GitHub Action wrapper
|
|
39
|
+
- `src/spec.test.ts` — Spec + compiler test suite (node:test)
|
|
40
|
+
- `src/validate.test.ts` — Validation test suite (node:test)
|
|
41
|
+
- `src/cli.test.ts` — CLI integration + E2E test suite (node:test)
|
|
42
|
+
- `src/proofs.ts` — Deterministic proof algorithms (monotonicity lattice, NCD, Bloom filter, Merkle DAG, fixed-point, property testing)
|
|
43
|
+
- `src/evolve.ts` — Evolution engine: mutation operators, fitness function, proof-gated selection
|
|
44
|
+
- `src/proofs.test.ts` — Proof system + evolution engine tests (node:test)
|
|
45
|
+
- `CLAUDE.md.spec.ts` — This file — the source of truth for CLAUDE.md
|
|
46
|
+
- `examples/SKILL.md.spec.ts` — Example SKILL.md spec
|
|
47
|
+
- `research/adoption-strategy.md` — Adoption strategy: zero-config setup, progressive enforcement, agent workflows
|
|
48
|
+
- `research/competitive-landscape.md` — Competitive landscape: rule-porter, rulesync, vibe-cli, Ruler
|
|
49
|
+
- `research/executable-specs.md` — Design doc: executable spec system
|
|
50
|
+
- `research/feature-ideas.md` — Feature ideas: plugin API, custom rules, exhaustive coverage
|
|
51
|
+
- `research/ai-code-quality.md` — Research: AI code quality patterns
|
|
52
|
+
- `research/self-evolving-specs.md` — Design doc: self-evolving spec system (proofs, Merkle history, evolution engine)
|
|
53
|
+
- `research/code-search-for-agents.md` — Research: code search approaches (grep vs embeddings vs AST-grep)
|
|
54
|
+
- `docs/agent-workflows.md` — Agent-specific workflows (Claude Code, Codex, multi-agent, Cursor)
|
|
55
|
+
- `docs/agent-setup.md` — Non-interactive agent setup guide (hooks via settings.json)
|
|
56
|
+
- `docs/spec-format.md` — Spec format reference (target, sections, rules)
|
|
57
|
+
- `docs/linter-support.md` — Linter support details (6 linters + generate-types)
|
|
58
|
+
- `docs/inline-mode.md` — Inline mode: `<!-- vigiles:enforce ... -->` comments for gradual adoption without a .spec.ts
|
|
59
|
+
|
|
60
|
+
## Commands
|
|
61
|
+
|
|
62
|
+
- `npm run build` — Compile TypeScript to dist/
|
|
63
|
+
- `npm test` — Build and run all tests
|
|
64
|
+
- `npm run fmt` — Format with prettier
|
|
65
|
+
- `npm run fmt:check` — Check formatting
|
|
66
|
+
|
|
67
|
+
## Rules
|
|
68
|
+
|
|
69
|
+
### Never Skip Tests
|
|
70
|
+
|
|
71
|
+
**Guidance only** — All tests must pass. If a test requires a CLI tool (pylint, rubocop, ruff, clippy), install the tool, don't skip the test.
|
|
72
|
+
|
|
73
|
+
### Zero Config By Default
|
|
74
|
+
|
|
75
|
+
**Guidance only** — `vigiles compile` should work with just a .spec.ts file. Config exists only for overrides (maxRules, maxTokens).
|
|
76
|
+
|
|
77
|
+
### Dont Reimplement Linters
|
|
78
|
+
|
|
79
|
+
**Guidance only** — Architectural linting belongs in ast-grep/Dependency Cruiser/Steiger. Per-file code rules belong in ESLint/Ruff/Clippy. vigiles owns: spec compilation, linter cross-referencing, type generation, stale reference detection, and proof-based spec evolution.
|
|
80
|
+
|
|
81
|
+
### Smooth Adoption
|
|
82
|
+
|
|
83
|
+
**Guidance only** — `npx vigiles init && npx skills add zernie/vigiles` must work on first run with zero config. The wizard auto-detects the project, creates specs, generates types, compiles, and wires CI. After install the agent edits specs automatically — no workflow change required. Start permissive (guidance rules, `require-spec: false` available), tighten over time. Hesitant adopters can use inline mode (`<!-- vigiles:enforce ... -->` comments) without a .spec.ts — see `docs/inline-mode.md`. See `research/adoption-strategy.md`.
|
|
84
|
+
|
|
85
|
+
### Format Before Commit
|
|
86
|
+
|
|
87
|
+
**Guidance only** — Run `npm run fmt:check` before committing. Inline code spans in markdown need surrounding spaces to render correctly.
|
|
88
|
+
|
|
89
|
+
### Progressive Adoption
|
|
90
|
+
|
|
91
|
+
**Guidance only** — vigiles must be adoptable incrementally, like TypeScript. Three on-ramps, zero friction: (1) inline mode — add `<!-- vigiles:enforce ... -->` comments to an existing CLAUDE.md, no new files; (2) spec mode with `guidance()` only — `npx vigiles init` creates a .spec.ts, compiles to markdown, zero linter setup; (3) strict mode — `enforce()` rules, CI gating, `--strict` flag. Each level adds value without requiring the next. Never gate basic functionality on advanced setup. README examples should always show the simplest path first.
|
|
92
|
+
|
|
93
|
+
### No Session Links
|
|
94
|
+
|
|
95
|
+
**Guidance only** — This is a public repo. Claude Code session URLs are private and must not appear in commits or PRs.
|