@lifeaitools/rdc-skills 0.34.0 → 0.35.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-plugin/plugin.json +284 -1
- package/VALIDATOR-ARCHITECTURE.md +534 -0
- package/commands/analyze-tests.md +11 -0
- package/commands/check-clean-code.md +11 -0
- package/commands/check-packages.md +10 -0
- package/commands/compare-compliance.md +14 -0
- package/commands/full-analysis.md +50 -0
- package/commands/get-refactoring-plan.md +13 -0
- package/commands/quick-check.md +13 -0
- package/commands/recover.md +149 -0
- package/commands/review-arch.md +12 -0
- package/commands/review.md +12 -113
- package/commands/suggest-patterns.md +11 -0
- package/commands/validate-solid.md +11 -0
- package/package.json +14 -2
- package/scripts/architecture-score.mjs +157 -0
- package/scripts/clean-code-score.mjs +177 -0
- package/scripts/duplication-score.mjs +66 -0
- package/scripts/lib/architecture-scoring.mjs +695 -0
- package/scripts/lib/clean-code-scoring.mjs +258 -0
- package/scripts/lib/duplication-scoring.mjs +238 -0
- package/scripts/lib/language-plugin.mjs +82 -0
- package/scripts/lib/package-metrics.mjs +439 -0
- package/scripts/lib/pattern-scoring.mjs +351 -0
- package/scripts/lib/plugins/treesitter.mjs +1182 -0
- package/scripts/lib/plugins/typescript.mjs +672 -0
- package/scripts/lib/refactoring-scoring.mjs +307 -0
- package/scripts/lib/solid-scoring.mjs +101 -0
- package/scripts/lib/test-smell-scoring.mjs +581 -0
- package/scripts/lib/vendor/codeflow-parser/.source-commit +1 -0
- package/scripts/lib/vendor/codeflow-parser/grammars.d.ts +23 -0
- package/scripts/lib/vendor/codeflow-parser/grammars.js +57 -0
- package/scripts/lib/vendor/codeflow-parser/memberFacts.d.ts +274 -0
- package/scripts/lib/vendor/codeflow-parser/memberFacts.js +1117 -0
- package/scripts/lib/vendor/codeflow-parser/nativeParser.d.ts +115 -0
- package/scripts/lib/vendor/codeflow-parser/nativeParser.js +759 -0
- package/scripts/lib/vendor/codeflow-parser/package.json +3 -0
- package/scripts/lib/vendor/codeflow-parser/xmlParser.d.ts +77 -0
- package/scripts/lib/vendor/codeflow-parser/xmlParser.js +400 -0
- package/scripts/package-metrics-cli.mjs +112 -0
- package/scripts/pattern-score.mjs +143 -0
- package/scripts/refactoring-score.mjs +253 -0
- package/scripts/solid-score.mjs +337 -0
- package/skills/architecture-reviewer/SKILL.md +287 -0
- package/skills/clean-code-analyzer/SKILL.md +147 -0
- package/skills/package-design/SKILL.md +118 -0
- package/skills/pattern-advisor/SKILL.md +237 -0
- package/skills/pattern-refactoring-guide/SKILL.md +262 -0
- package/skills/review/SKILL.md +29 -0
- package/skills/solid-validator/SKILL.md +92 -0
- package/skills/testing-strategy/SKILL.md +132 -0
- package/tests/lib/architecture-scoring.test.mjs +335 -0
- package/tests/lib/clean-code-scoring.test.mjs +241 -0
- package/tests/lib/duplication-scoring.test.mjs +144 -0
- package/tests/lib/fixtures.mjs +58 -0
- package/tests/lib/package-metrics.test.mjs +241 -0
- package/tests/lib/pattern-scoring.test.mjs +251 -0
- package/tests/lib/refactoring-scoring.test.mjs +264 -0
- package/tests/lib/solid-scoring.test.mjs +291 -0
- package/tests/lib/test-smell-scoring.test.mjs +281 -0
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: full-analysis
|
|
3
|
+
description: >-
|
|
4
|
+
Usage `rdc:full-analysis <path> [--diff <ref>]` — runs all seven surfaces
|
|
5
|
+
(solid-validator, architecture-reviewer, clean-code-analyzer,
|
|
6
|
+
package-design, pattern-advisor, testing-strategy, and
|
|
7
|
+
pattern-refactoring-guide on anything the others flag) and merges into
|
|
8
|
+
one report. The full form/fit/function pass — use before merging a new
|
|
9
|
+
package or a significant refactor, not for routine edits.
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
> **⚠️ OUTPUT CONTRACT (READ FIRST):** `guides/output-contract.md`
|
|
13
|
+
> Checklist-only output. No tool-call narration. No raw MCP/JSON/log dumps.
|
|
14
|
+
> One checklist upfront, updated in place, shown again at end with a 1-line verdict.
|
|
15
|
+
|
|
16
|
+
# full-analysis — Complete Form/Fit/Function Pass
|
|
17
|
+
|
|
18
|
+
## Order — mechanical first, judgment second, refactor plans last
|
|
19
|
+
|
|
20
|
+
1. **FORM** — Skill tool, skill: "solid-validator" (path, `--diff`)
|
|
21
|
+
2. **FIT** — Skill tool, skill: "architecture-reviewer" (path, `--diff`) —
|
|
22
|
+
reuses step 1's `boundaryFindings`, does not re-run the mechanical check.
|
|
23
|
+
3. **FUNCTION** — Skill tool, skill: "testing-strategy" (path)
|
|
24
|
+
4. **Naming/dead-code/complexity** — Skill tool, skill: "clean-code-analyzer"
|
|
25
|
+
5. **Package boundaries** — Skill tool, skill: "package-design"
|
|
26
|
+
6. **Patterns** — Skill tool, skill: "pattern-advisor"
|
|
27
|
+
7. **For every HIGH/CRITICAL finding from steps 1-6** — Skill tool, skill:
|
|
28
|
+
"pattern-refactoring-guide", one dispatch per finding, producing a
|
|
29
|
+
concrete plan.
|
|
30
|
+
|
|
31
|
+
## Report
|
|
32
|
+
|
|
33
|
+
```
|
|
34
|
+
## Full Analysis — <path>
|
|
35
|
+
### FORM (solid-validator)
|
|
36
|
+
### FIT (architecture-reviewer)
|
|
37
|
+
### FUNCTION (testing-strategy)
|
|
38
|
+
### Clean Code
|
|
39
|
+
### Package Design
|
|
40
|
+
### Pattern Suggestions
|
|
41
|
+
### Refactor Plans (for every high/critical finding above)
|
|
42
|
+
## Verdict: CLEAN / HAS ISSUES
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## Rules
|
|
46
|
+
|
|
47
|
+
- Do not re-run the mechanical boundary check inside step 2 — pass step 1's
|
|
48
|
+
result through.
|
|
49
|
+
- A CLEAN verdict requires all seven surfaces to report clean, not a
|
|
50
|
+
majority.
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: get-refactoring-plan
|
|
3
|
+
description: >-
|
|
4
|
+
Usage `rdc:get-refactoring-plan <finding>` — turns a solid-validator/
|
|
5
|
+
architecture-reviewer/pattern-advisor finding into a step-ordered
|
|
6
|
+
before/after refactor plan. Produces a plan, does not apply it. See
|
|
7
|
+
skills/pattern-refactoring-guide.
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# get-refactoring-plan
|
|
11
|
+
|
|
12
|
+
Use Skill tool with skill: "pattern-refactoring-guide", passing the finding
|
|
13
|
+
(file:line + source skill) as args.
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: quick-check
|
|
3
|
+
description: >-
|
|
4
|
+
Usage `rdc:quick-check <path>` — fast mechanical-only pass: solid-validator
|
|
5
|
+
score + boundary check. No dispatched judgment agents. For a tight
|
|
6
|
+
iteration loop, not a merge gate.
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# quick-check
|
|
10
|
+
|
|
11
|
+
Use Skill tool with skill: "solid-validator", passing the path as args.
|
|
12
|
+
This is the mechanical-only subset — no judgment dispatch, meant to run in
|
|
13
|
+
seconds during active editing. Use `full-analysis` before a merge.
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: recover
|
|
3
|
+
description: >-
|
|
4
|
+
Usage `rdc:recover [list|start]` — deterministic post-crash recovery: detect, repair (CodeFlow/PM2 only), verify, then find and resume abandoned Claude/Codex worktree-lane sessions.
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
> **⚠️ OUTPUT CONTRACT (READ FIRST):** `guides/output-contract.md`
|
|
8
|
+
> Checklist-only output. No tool-call narration. No raw MCP/JSON/log dumps.
|
|
9
|
+
> One checklist upfront, updated in place, shown again at end with a 1-line verdict.
|
|
10
|
+
|
|
11
|
+
> **Sandbox contract:** This skill honors `RDC_TEST=1` per `guides/agent-bootstrap.md` §
|
|
12
|
+
> RDC_TEST Sandbox Contract. Under `$RDC_TEST=1`, Phase 3 (REPAIR) is skipped —
|
|
13
|
+
> echo `[RDC_TEST] skipping CodeFlow/PM2 repair` and proceed. DETECT, DIAGNOSE, VERIFY,
|
|
14
|
+
> and SESSIONS are all read-only probes and run normally.
|
|
15
|
+
|
|
16
|
+
# rdc:recover — post-crash session recovery
|
|
17
|
+
|
|
18
|
+
## When to Use
|
|
19
|
+
- After a box crash, terminal-window crash, or unclean shutdown
|
|
20
|
+
- Checking whether any Claude/Codex worktree-lane session was mid-work when it happened
|
|
21
|
+
- Resuming a session that got abandoned, without hunting for its id by hand
|
|
22
|
+
|
|
23
|
+
## The one thing to understand first
|
|
24
|
+
|
|
25
|
+
**This is a script, not a hunt.** All the actual logic — crash detection, engine-specific
|
|
26
|
+
liveness, lane classification, self-elevation to a visible window — lives in the project's
|
|
27
|
+
own `scripts/box-recovery.ps1` / `scripts/recover-session.ps1` / `scripts/lib/session-detect.ps1`.
|
|
28
|
+
This skill is a thin, deterministic dispatcher onto those scripts. Do not reimplement any of
|
|
29
|
+
their classification logic here, and do not improvise an alternate repair path if a phase
|
|
30
|
+
fails — report the failure with its exact command + output instead.
|
|
31
|
+
|
|
32
|
+
**Both scripts self-elevate to a real, persistent, visible terminal window on their own** —
|
|
33
|
+
they detect a non-interactive invocation (`[Console]::IsOutputRedirected`, true when your
|
|
34
|
+
tool call captures/pipes their output) and relaunch themselves via `wt.exe new-tab`, then
|
|
35
|
+
exit immediately. Do NOT manually wrap them in your own `wt.exe` call — just invoke the
|
|
36
|
+
script directly. That used to be the caller's job and got done wrong repeatedly live; it's
|
|
37
|
+
the script's own job now.
|
|
38
|
+
|
|
39
|
+
## Usage
|
|
40
|
+
|
|
41
|
+
```
|
|
42
|
+
rdc:recover # full pipeline — detect, repair, verify, report+offer sessions
|
|
43
|
+
rdc:recover list # report only — no repair, no launch, no prompt
|
|
44
|
+
rdc:recover start # skip detect/diagnose/repair/verify — just resume matched sessions
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Subcommands
|
|
48
|
+
|
|
49
|
+
### `rdc:recover` (no argument) — full pipeline
|
|
50
|
+
|
|
51
|
+
Resolve the caller's actual project root first (never assume it's this plugin's own repo):
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
ROOT=$(git rev-parse --show-toplevel)
|
|
55
|
+
pwsh -File "$ROOT/scripts/box-recovery.ps1"
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Deterministic, five phases in order — do not skip ahead, do not improvise alternate repair
|
|
59
|
+
commands:
|
|
60
|
+
|
|
61
|
+
1. **DETECT** — was there actually an unclean shutdown (Kernel-Power Event 41), and is
|
|
62
|
+
memory/commit charge under pressure right now.
|
|
63
|
+
2. **DIAGNOSE** — is CodeFlow's local gateway (`:3109`) up, is the local PM2 process table
|
|
64
|
+
empty (nothing resurrected after reboot).
|
|
65
|
+
3. **REPAIR** — owner-sanctioned repair only: `node scripts/codeflow-repair.mjs` for
|
|
66
|
+
CodeFlow, `pm2 resurrect` for the local PM2 fleet. **Never** auto-starts an app named
|
|
67
|
+
`rtp` even if it's in the saved PM2 dump — see the script's own header for why. Do not
|
|
68
|
+
override that by hand-invoking `pm2 start rtp`.
|
|
69
|
+
4. **VERIFY** — `pnpm agent:readiness` must report `ok:true`, plus a live probe of clauth
|
|
70
|
+
(`:52437/ping`) and CodeFlow (`:3109/health`). Do not report recovery as complete on
|
|
71
|
+
anything less than a live probe.
|
|
72
|
+
5. **SESSIONS** — reports every worktree lane that was mid-session at crash time and is not
|
|
73
|
+
live right now (`aborted`), lanes with a crash-window transcript that have already
|
|
74
|
+
reattached (`✅ Already recovered`), and general stale lanes unrelated to this crash
|
|
75
|
+
(`orphan`). Prints exact resume commands for everything pending, then offers one
|
|
76
|
+
interactive prompt to resume some/all of it. A lane whose session engine doesn't match
|
|
77
|
+
its lane's owning engine (a Claude session in an `x-codex-*` lane, or vice versa) is
|
|
78
|
+
reported as a `LANE MISMATCH` and is a HARD RULE never launched, under any flag.
|
|
79
|
+
|
|
80
|
+
Because this launches a real visible window and its own interactive prompt, when running as
|
|
81
|
+
an agent (no human at that window to answer it) do not rely on the bare form to resume
|
|
82
|
+
anything — the window opens, the prompt waits, nothing gets resumed until a human answers
|
|
83
|
+
it. Report that the window is open and stop there. To have the agent itself resume sessions
|
|
84
|
+
non-interactively, use `rdc:recover start` below instead.
|
|
85
|
+
|
|
86
|
+
### `rdc:recover list` — report only, no repair, no launch, no prompt
|
|
87
|
+
|
|
88
|
+
Skips the entire detect/diagnose/repair/verify stack entirely. Pure report:
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
ROOT=$(git rev-parse --show-toplevel)
|
|
92
|
+
pwsh -File "$ROOT/scripts/recover-session.ps1" -ListOnly
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
Add `-All` for the full inventory including `live` and `clean` lanes, not just
|
|
96
|
+
`aborted`/`orphan`.
|
|
97
|
+
|
|
98
|
+
### `rdc:recover start` — resume, skipping the whole recovery stack
|
|
99
|
+
|
|
100
|
+
Also skips detect/diagnose/repair/verify — this is the addressable primitive, not the
|
|
101
|
+
crash orchestrator. Since an agent invoking this has no human sitting at the window to
|
|
102
|
+
answer an interactive prompt, always pass `-Launch` explicitly to skip it:
|
|
103
|
+
|
|
104
|
+
```bash
|
|
105
|
+
ROOT=$(git rev-parse --show-toplevel)
|
|
106
|
+
|
|
107
|
+
# all matched (aborted + orphan by default; narrow with -Status/-Engine/-Role)
|
|
108
|
+
pwsh -File "$ROOT/scripts/recover-session.ps1" -Launch
|
|
109
|
+
|
|
110
|
+
# one specific session
|
|
111
|
+
pwsh -File "$ROOT/scripts/recover-session.ps1" -Id <sessionId> -Launch
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
## After launching, in every subcommand
|
|
115
|
+
|
|
116
|
+
Tell the user the window is open and to watch/answer it there — do not try to relay live
|
|
117
|
+
phase-by-phase output, you don't have it. If you need to verify the result yourself (e.g.
|
|
118
|
+
to answer a follow-up), read the run-record log the script writes on completion under
|
|
119
|
+
`C:\Dev\.logs\regen-root\<script-name>\<date>\` (newest file), rather than re-running the
|
|
120
|
+
script a second time in your own context.
|
|
121
|
+
|
|
122
|
+
## Rules
|
|
123
|
+
|
|
124
|
+
- **Never reimplement the classification logic in this skill.** Engine-specific liveness,
|
|
125
|
+
crash-window matching, lane-mismatch detection, and orphan/aborted status all live in
|
|
126
|
+
`scripts/lib/session-detect.ps1` — read it if you need to understand *why* a session was
|
|
127
|
+
classified a certain way, never re-derive the answer independently.
|
|
128
|
+
- **Lane mismatch is never launched, under any flag or filter.** A Claude session found
|
|
129
|
+
sitting in a Codex-owned lane (or vice versa) is a HARD RULE violation if resumed there —
|
|
130
|
+
both scripts already enforce this; do not work around it.
|
|
131
|
+
- **If any phase fails, report exactly what failed and why** (cited command + output) — do
|
|
132
|
+
not guess a cause or invent a fix outside the script's own repair paths. If CodeFlow
|
|
133
|
+
repair itself fails, that is CodeFlow's own failure: report it, do not hand-patch
|
|
134
|
+
`packages/codeflow`.
|
|
135
|
+
- **Do not disrupt what you're trying to recover.** Never restart clauth, CodeFlow, or PM2
|
|
136
|
+
mid-diagnosis as a troubleshooting step — that can BE the reason a symptom changes.
|
|
137
|
+
- **-AutoRun's launch (if the caller wires this into logon) stays scoped to crash casualties
|
|
138
|
+
only.** Orphan lanes are reported for visibility but never silently auto-launched on an
|
|
139
|
+
unrelated crash's recovery run — see `box-recovery.ps1`'s own `$launchSet` handling.
|
|
140
|
+
|
|
141
|
+
## Verification
|
|
142
|
+
|
|
143
|
+
The scripts themselves are the source of truth; this skill does not carry its own test
|
|
144
|
+
suite. To verify a change to the underlying scripts, from the caller's project root:
|
|
145
|
+
|
|
146
|
+
```bash
|
|
147
|
+
pwsh -Command '$e=$null; [System.Management.Automation.Language.Parser]::ParseFile("scripts/box-recovery.ps1", [ref]$null, [ref]$e); if ($e.Count -gt 0) { $e } else { "OK" }'
|
|
148
|
+
pwsh -File scripts/recover-session.ps1 -ListOnly -All -NoSelfElevate
|
|
149
|
+
```
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: review-arch
|
|
3
|
+
description: >-
|
|
4
|
+
Usage `rdc:review-arch <path> [--diff <ref>]` — layering/dependency-
|
|
5
|
+
direction review, mechanical + judgment (FIT corner). See
|
|
6
|
+
skills/architecture-reviewer.
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# review-arch
|
|
10
|
+
|
|
11
|
+
Use Skill tool with skill: "architecture-reviewer", passing the path and any
|
|
12
|
+
`--diff` flag as args.
|
package/commands/review.md
CHANGED
|
@@ -1,120 +1,19 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: review
|
|
3
3
|
description: >-
|
|
4
|
-
Usage `rdc:review [--unattended]` —
|
|
4
|
+
Usage `rdc:review [--unattended]` — post-build quality gate: tsc, tests,
|
|
5
|
+
stale docs, export conflicts, a mandatory pr-review-toolkit:code-reviewer
|
|
6
|
+
pass, and the form/fit/function gate (solid-validator + architecture-
|
|
7
|
+
reviewer) across modified packages. See skills/review.
|
|
5
8
|
---
|
|
6
9
|
|
|
7
|
-
|
|
8
|
-
> Checklist-only output. No tool-call narration. No raw MCP/JSON/log dumps.
|
|
9
|
-
> One checklist upfront, updated in place, shown again at end with a 1-line verdict.
|
|
10
|
+
# review
|
|
10
11
|
|
|
11
|
-
|
|
12
|
+
Use Skill tool with skill: "review", passing `--unattended` through if given.
|
|
12
13
|
|
|
13
|
-
>
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
- After a build session (especially overnight builds)
|
|
20
|
-
- Before merging development → main/production
|
|
21
|
-
- Project lead asks "review the work", "is everything clean"
|
|
22
|
-
- Before any production deployment
|
|
23
|
-
- Called by `rdc:overnight` after each epic build completes
|
|
24
|
-
|
|
25
|
-
## Arguments
|
|
26
|
-
- `rdc:review` — interactive review, pauses on issues needing judgment
|
|
27
|
-
- `rdc:review --unattended` — silent mode, auto-fixes everything fixable
|
|
28
|
-
|
|
29
|
-
## Procedure
|
|
30
|
-
|
|
31
|
-
1. **Identify modified packages:**
|
|
32
|
-
```bash
|
|
33
|
-
git diff --name-only origin/main...HEAD | grep "^packages/" | cut -d/ -f2 | sort -u
|
|
34
|
-
```
|
|
35
|
-
|
|
36
|
-
2. **Run tests for each modified package:**
|
|
37
|
-
```bash
|
|
38
|
-
cd packages/<name> && npx vitest run 2>&1 | tail -10
|
|
39
|
-
```
|
|
40
|
-
Report: package → test count → pass/fail → new tests added
|
|
41
|
-
|
|
42
|
-
**IMPORTANT:** `pnpm build` must NEVER be run (crashes system). Use `npx tsc --noEmit --project <path>/tsconfig.json` for typecheck instead. For packages without tests, typecheck is the verification method. Do NOT run vitest across the entire monorepo — check only modified packages individually.
|
|
43
|
-
|
|
44
|
-
3. **Check test coverage delta:**
|
|
45
|
-
```bash
|
|
46
|
-
git diff origin/main...HEAD -- packages/*/src/ | grep -c "^+" | head -5
|
|
47
|
-
git diff origin/main...HEAD -- packages/*/test* packages/*/src/**/*.test.* packages/*/src/**/*.spec.* 2>/dev/null | grep -c "^+" || echo 0
|
|
48
|
-
```
|
|
49
|
-
Flag any package where implementation lines added > 50 but test lines added = 0.
|
|
50
|
-
|
|
51
|
-
4. **Check for export conflicts:**
|
|
52
|
-
- Read `packages/*/src/index.ts` for any package with new exports
|
|
53
|
-
- Look for duplicate export names across the barrel
|
|
54
|
-
- Verify aliased exports don't shadow each other
|
|
55
|
-
|
|
56
|
-
5. **Check for TODO/FIXME/HACK:**
|
|
57
|
-
```bash
|
|
58
|
-
grep -rn "TODO\|FIXME\|HACK\|XXX" packages/*/src/ --include="*.ts" --include="*.tsx"
|
|
59
|
-
```
|
|
60
|
-
|
|
61
|
-
6. **Check package versions:**
|
|
62
|
-
- Any package with significant new code should have a version bump
|
|
63
|
-
- Compare package.json versions to what's in `docs/SYSTEM-STATE.md`
|
|
64
|
-
|
|
65
|
-
7. **Check for stale CLAUDE.md:**
|
|
66
|
-
- If new modules were added to a package, does its CLAUDE.md mention them?
|
|
67
|
-
- Flag any package where exports grew by >10 lines but CLAUDE.md wasn't updated
|
|
68
|
-
|
|
69
|
-
8. **Orphan work item audit:**
|
|
70
|
-
```sql
|
|
71
|
-
SELECT id, title, item_type, status, source, created_at::date
|
|
72
|
-
FROM work_items
|
|
73
|
-
WHERE parent_id IS NULL
|
|
74
|
-
AND item_type NOT IN ('epic', 'bug')
|
|
75
|
-
AND status NOT IN ('done', 'archived')
|
|
76
|
-
ORDER BY created_at DESC;
|
|
77
|
-
```
|
|
78
|
-
For each orphaned task found:
|
|
79
|
-
- If it clearly belongs to an open epic → attach it: `UPDATE work_items SET parent_id = '<epic-id>' WHERE id = '<task-id>'`
|
|
80
|
-
- If unclear → report (interactive) or flag in REVIEW_STATUS (unattended)
|
|
81
|
-
- Never silently leave orphaned tasks
|
|
82
|
-
|
|
83
|
-
9. **Verification gate — dispatch the verify agent:**
|
|
84
|
-
After any fixes land, run the verify gate on every touched package. See `guides/agents/verify.md`.
|
|
85
|
-
**Iron Law: no CLEAN verdict without fresh evidence.** Quote the vitest + tsc output in the report.
|
|
86
|
-
If verify fails → do NOT emit CLEAN. Loop back, fix, re-run verify.
|
|
87
|
-
|
|
88
|
-
10. **Fix issues found:**
|
|
89
|
-
- Failing tests → fix and commit
|
|
90
|
-
- Export conflicts → resolve and commit
|
|
91
|
-
- Missing version bumps → bump and commit
|
|
92
|
-
- All fixes as separate commits with descriptive messages
|
|
93
|
-
|
|
94
|
-
**Judgment calls:**
|
|
95
|
-
- Interactive: report — don't guess
|
|
96
|
-
- Unattended: escalate via advisor tool with: error message, surrounding context,
|
|
97
|
-
two most likely fix paths. Resume with advisor's recommendation.
|
|
98
|
-
If advisor unavailable: take the most conservative path, flag in status block.
|
|
99
|
-
|
|
100
|
-
11. **Report:**
|
|
101
|
-
- Interactive:
|
|
102
|
-
```
|
|
103
|
-
## Review Results
|
|
104
|
-
| Package | Tests | Pass/Fail | New Tests | Issues |
|
|
105
|
-
## Fixed
|
|
106
|
-
## Remaining Issues
|
|
107
|
-
## Verdict: CLEAN / HAS ISSUES
|
|
108
|
-
```
|
|
109
|
-
- Unattended: emit status block only:
|
|
110
|
-
```
|
|
111
|
-
REVIEW_STATUS: { verdict: "CLEAN|HAS_ISSUES", packages_checked, tests_passed, tests_failed, new_tests_added, fixes_applied, escalations }
|
|
112
|
-
```
|
|
113
|
-
|
|
114
|
-
## Rules
|
|
115
|
-
- Do NOT run `pnpm build` (crashes system) — vitest only
|
|
116
|
-
- Interactive: fix what you can, flag what needs decision
|
|
117
|
-
- Unattended: fix everything fixable; escalate judgment calls to advisor
|
|
118
|
-
- Each fix is a separate commit (not batched)
|
|
119
|
-
- Always push fixes to origin after committing *(skip if `$RDC_TEST=1` — echo `[RDC_TEST] skipping git push` instead)*
|
|
120
|
-
- Unattended: NEVER pause for input
|
|
14
|
+
> This file previously carried a full duplicate of the procedure now owned by
|
|
15
|
+
> `skills/review/SKILL.md`. The two drifted — this copy was missing the
|
|
16
|
+
> mandatory code-review gate (step 8b) and the `engineering-behavior.md` read
|
|
17
|
+
> that the other had. One home for the content closes that class of bug
|
|
18
|
+
> permanently rather than requiring the next editor to remember to update
|
|
19
|
+
> both.
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: suggest-patterns
|
|
3
|
+
description: >-
|
|
4
|
+
Usage `rdc:suggest-patterns <path>` — design pattern suggestions,
|
|
5
|
+
advisory only, "no pattern needed" is a valid verdict. See
|
|
6
|
+
skills/pattern-advisor.
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# suggest-patterns
|
|
10
|
+
|
|
11
|
+
Use Skill tool with skill: "pattern-advisor", passing the path as args.
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: validate-solid
|
|
3
|
+
description: >-
|
|
4
|
+
Usage `rdc:validate-solid <path> [--diff <ref>]` — deterministic SOLID +
|
|
5
|
+
Clean Architecture scoring (FORM corner). See skills/solid-validator.
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# validate-solid
|
|
9
|
+
|
|
10
|
+
Use Skill tool with skill: "solid-validator", passing the path and any
|
|
11
|
+
`--diff`/`--config` flags as args.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lifeaitools/rdc-skills",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.35.0",
|
|
4
4
|
"description": "RDC typed-agent dispatch skill suite for Claude Code - plan, build, review, overnight builds",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"claude-code",
|
|
@@ -25,9 +25,18 @@
|
|
|
25
25
|
"bin": {
|
|
26
26
|
"rdc-skills-install": "scripts/install-rdc-skills.js",
|
|
27
27
|
"rdc-skills-self-test": "scripts/self-test.mjs",
|
|
28
|
-
"rdc-skills-mcp": "bin/rdc-skills-mcp.mjs"
|
|
28
|
+
"rdc-skills-mcp": "bin/rdc-skills-mcp.mjs",
|
|
29
|
+
"rdc-solid-score": "scripts/solid-score.mjs",
|
|
30
|
+
"rdc-clean-code-score": "scripts/clean-code-score.mjs",
|
|
31
|
+
"rdc-package-metrics": "scripts/package-metrics-cli.mjs",
|
|
32
|
+
"rdc-architecture-score": "scripts/architecture-score.mjs",
|
|
33
|
+
"rdc-pattern-score": "scripts/pattern-score.mjs",
|
|
34
|
+
"rdc-refactoring-score": "scripts/refactoring-score.mjs",
|
|
35
|
+
"rdc-test-smell-score": "scripts/lib/test-smell-scoring.mjs",
|
|
36
|
+
"rdc-duplication-score": "scripts/duplication-score.mjs"
|
|
29
37
|
},
|
|
30
38
|
"scripts": {
|
|
39
|
+
"test:validator": "node --test tests/lib/*.test.mjs",
|
|
31
40
|
"postinstall": "node scripts/postinstall.js",
|
|
32
41
|
"install-rdc-skills": "node scripts/install-rdc-skills.js",
|
|
33
42
|
"uninstall:win": "powershell -ExecutionPolicy Bypass -File scripts/uninstall.ps1",
|
|
@@ -51,6 +60,9 @@
|
|
|
51
60
|
"dependencies": {
|
|
52
61
|
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
53
62
|
"express": "^5.0.0",
|
|
63
|
+
"tree-sitter-wasms": "^0.1.13",
|
|
64
|
+
"ts-morph": "^24.0.0",
|
|
65
|
+
"web-tree-sitter": "^0.24.7",
|
|
54
66
|
"yaml": "^2.9.0",
|
|
55
67
|
"zod": "^3.25.76"
|
|
56
68
|
}
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* architecture-score — mechanical Clean Architecture boundary / dependency-
|
|
4
|
+
* direction / layer-separation scoring, ported from
|
|
5
|
+
* github.com/OnSightTeam/architecture-toolkit (MIT) — see
|
|
6
|
+
* `lib/architecture-scoring.mjs`'s header for the full provenance and what
|
|
7
|
+
* was deliberately NOT ported (the toolkit's own broken circular-dependency
|
|
8
|
+
* check).
|
|
9
|
+
*
|
|
10
|
+
* Same architecture as `package-metrics-cli.mjs`: this file owns argv
|
|
11
|
+
* parsing, file discovery, config loading, and output formatting. It does
|
|
12
|
+
* NOT know what an AST is — `lib/architecture-scoring.mjs` is plain
|
|
13
|
+
* `node:fs` + regex/path parsing, independent of the ts-morph
|
|
14
|
+
* `language-plugin.mjs` used by SOLID/clean-code.
|
|
15
|
+
*
|
|
16
|
+
* Config (`--config <file>`, YAML) — same loading discipline as
|
|
17
|
+
* `solid-score.mjs`'s `--config`: an explicitly-passed path that doesn't
|
|
18
|
+
* exist is an error, not a silent fallback to defaults; an absent flag
|
|
19
|
+
* legitimately means "use `DEFAULT_LAYERS`."
|
|
20
|
+
*
|
|
21
|
+
* layers:
|
|
22
|
+
* - name: Entities
|
|
23
|
+
* level: 4
|
|
24
|
+
* globs: ["**\/entities/**", "**\/domain/**"]
|
|
25
|
+
*
|
|
26
|
+
* Usage:
|
|
27
|
+
* node architecture-score.mjs <path> [--config <file>] [--format text|json]
|
|
28
|
+
*
|
|
29
|
+
* DETERMINISM (ATF golden-record requirement): file walk order is sorted
|
|
30
|
+
* (see `walkSourceFiles`), every finding array is emitted in a stable order
|
|
31
|
+
* (files sorted by relPath, rule keys in a fixed object-literal order,
|
|
32
|
+
* cycles canonicalized+sorted), no absolute paths in output (every
|
|
33
|
+
* `location` is scan-root-relative), no timestamps. Verified by running
|
|
34
|
+
* this CLI twice against the same target and diffing — see the task report
|
|
35
|
+
* for the actual command and its empty diff.
|
|
36
|
+
*
|
|
37
|
+
* Exit code is always 0 — a reporting tool, not a gate (same policy as
|
|
38
|
+
* `package-metrics-cli.mjs`; nothing asked for a `--fail-on` this round).
|
|
39
|
+
*/
|
|
40
|
+
|
|
41
|
+
import { readFileSync, existsSync, statSync, realpathSync } from 'node:fs';
|
|
42
|
+
import path from 'node:path';
|
|
43
|
+
import { pathToFileURL } from 'node:url';
|
|
44
|
+
import { parse as parseYaml } from 'yaml';
|
|
45
|
+
|
|
46
|
+
import { walkSourceFiles, architectureScoreAll, DEFAULT_LAYERS } from './lib/architecture-scoring.mjs';
|
|
47
|
+
|
|
48
|
+
function arg(name, fallback = null) {
|
|
49
|
+
const i = process.argv.indexOf(name);
|
|
50
|
+
return i !== -1 ? process.argv[i + 1] : fallback;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Bash-tool / MSYS argv can hand this native-Windows process a POSIX-shaped
|
|
55
|
+
* path — normalize before use. Same fix as solid-score.mjs / clean-code-score.mjs.
|
|
56
|
+
*/
|
|
57
|
+
function normalizePath(p) {
|
|
58
|
+
const m = /^\/([A-Za-z])\/(.*)$/.exec(p);
|
|
59
|
+
const windowsShaped = m ? `${m[1].toUpperCase()}:/${m[2]}` : p;
|
|
60
|
+
const abs = path.resolve(process.cwd(), windowsShaped);
|
|
61
|
+
try {
|
|
62
|
+
return realpathSync(abs);
|
|
63
|
+
} catch {
|
|
64
|
+
return abs;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export function loadConfig(configPath) {
|
|
69
|
+
if (!configPath) return { layers: DEFAULT_LAYERS, configPath: null, configLoaded: false };
|
|
70
|
+
if (!existsSync(configPath)) throw new Error(`--config ${configPath} does not exist`);
|
|
71
|
+
const raw = parseYaml(readFileSync(configPath, 'utf8')) ?? {};
|
|
72
|
+
const layers = raw.layers ?? DEFAULT_LAYERS;
|
|
73
|
+
return { layers, configPath, configLoaded: true };
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function printHelp() {
|
|
77
|
+
console.error('Usage: node architecture-score.mjs <path> [--config <file>] [--format text|json]');
|
|
78
|
+
console.error('');
|
|
79
|
+
console.error(' <path> file or directory to scan (required)');
|
|
80
|
+
console.error(' --config <file> YAML file with a `layers:` section (see lib/architecture-scoring.mjs header). Default: DEFAULT_LAYERS (Entities/UseCases/InterfaceAdapters/Frameworks).');
|
|
81
|
+
console.error(' --format text (default) or json');
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function printText(output) {
|
|
85
|
+
for (const r of output.results) {
|
|
86
|
+
if (r.totalFindings === 0) continue;
|
|
87
|
+
console.log(`${r.file} [layer: ${r.layer ?? 'UNCLASSIFIED'}${r.layer ? ` via ${r.layerBasis}` : ''}] — ${r.totalFindings} finding(s)`);
|
|
88
|
+
for (const rule of Object.values(r.rules)) {
|
|
89
|
+
for (const f of rule.findings) {
|
|
90
|
+
console.log(` [${rule.ruleId}] [${f.severity}] [${f.confidence}] ${f.detail}`);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
if (output.circularLayerDependency.findings.length) {
|
|
95
|
+
console.log('\nCIRCULAR LAYER DEPENDENCIES:');
|
|
96
|
+
for (const f of output.circularLayerDependency.findings) console.log(` ${f.location}`);
|
|
97
|
+
} else {
|
|
98
|
+
console.log('\nNo circular layer dependencies found.');
|
|
99
|
+
}
|
|
100
|
+
if (output.unclassifiedFiles.length) {
|
|
101
|
+
console.log(`\n${output.unclassifiedFiles.length} file(s) matched no configured layer (path or name-hint) — skipped by every layer-aware rule, not silently passed as any specific layer:`);
|
|
102
|
+
for (const f of output.unclassifiedFiles) console.log(` ${f}`);
|
|
103
|
+
}
|
|
104
|
+
console.log(`\nLayers in effect: ${output.layers.map((l) => `${l.name}(${l.level})`).join(' > ')}`);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
async function main() {
|
|
108
|
+
const rawTarget = process.argv[2]?.startsWith('--') ? null : process.argv[2];
|
|
109
|
+
if (!rawTarget) {
|
|
110
|
+
printHelp();
|
|
111
|
+
process.exit(1);
|
|
112
|
+
}
|
|
113
|
+
const targetPath = normalizePath(rawTarget);
|
|
114
|
+
const configArg = arg('--config');
|
|
115
|
+
const format = arg('--format', 'text');
|
|
116
|
+
|
|
117
|
+
if (!existsSync(targetPath)) throw new Error(`target path does not exist: ${targetPath}`);
|
|
118
|
+
const { layers, configPath, configLoaded } = loadConfig(configArg ? normalizePath(configArg) : null);
|
|
119
|
+
|
|
120
|
+
const isFile = statSync(targetPath).isFile();
|
|
121
|
+
const root = isFile ? path.dirname(targetPath) : targetPath;
|
|
122
|
+
const files = isFile ? [targetPath] : walkSourceFiles(targetPath);
|
|
123
|
+
|
|
124
|
+
const scored = architectureScoreAll(files, root, { layers });
|
|
125
|
+
const output = {
|
|
126
|
+
results: scored.results,
|
|
127
|
+
circularLayerDependency: scored.circularLayerDependency,
|
|
128
|
+
unclassifiedFiles: scored.unclassifiedFiles,
|
|
129
|
+
layers: scored.layers,
|
|
130
|
+
config: { configPath, configLoaded, layerRuleCount: layers.length },
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
if (format === 'json') {
|
|
134
|
+
console.log(JSON.stringify(output, null, 2));
|
|
135
|
+
} else {
|
|
136
|
+
printText(output);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
process.exit(0);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
function realFileURL(p) {
|
|
143
|
+
try {
|
|
144
|
+
return pathToFileURL(realpathSync(p)).href;
|
|
145
|
+
} catch {
|
|
146
|
+
return pathToFileURL(p).href;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
const isMain = process.argv[1] && import.meta.url === realFileURL(process.argv[1]);
|
|
150
|
+
if (isMain) {
|
|
151
|
+
main().catch((err) => {
|
|
152
|
+
console.error(err.stack || String(err));
|
|
153
|
+
process.exit(2);
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
export { normalizePath };
|