jorgex-stack 1.0.1 → 1.0.3

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.
Files changed (99) hide show
  1. package/PRD.md +310 -297
  2. package/README.md +68 -56
  3. package/dist/cli.js +37 -3
  4. package/package.json +1 -1
  5. package/stack/agents/code-simplifier.md +21 -10
  6. package/stack/agents/implementer.md +1 -0
  7. package/stack/agents/orchestrator.md +194 -192
  8. package/stack/agents/security-auditor.md +7 -0
  9. package/stack/agents/silent-failure-hunter.md +7 -0
  10. package/stack/agents/test-analyzer.md +7 -0
  11. package/stack/agents/tester.md +71 -71
  12. package/stack/agents/type-design-analyzer.md +1 -1
  13. package/stack/commands/lean-audit.md +59 -0
  14. package/stack/commands/xreview.md +82 -80
  15. package/stack/hooks/hooks.json +18 -18
  16. package/stack/scripts/post-pr-review.cjs +159 -156
  17. package/stack/skills/diagnose/SKILL.md +117 -117
  18. package/stack/skills/diagnose/scripts/hitl-loop.template.sh +41 -41
  19. package/stack/skills/find-skills/SKILL.md +133 -133
  20. package/stack/skills/lean-code/SKILL.md +69 -0
  21. package/stack/skills/mcp-builder/LICENSE.txt +201 -201
  22. package/stack/skills/mcp-builder/SKILL.md +236 -236
  23. package/stack/skills/mcp-builder/reference/evaluation.md +601 -601
  24. package/stack/skills/mcp-builder/reference/mcp_best_practices.md +249 -249
  25. package/stack/skills/mcp-builder/reference/node_mcp_server.md +969 -969
  26. package/stack/skills/mcp-builder/reference/python_mcp_server.md +718 -718
  27. package/stack/skills/mcp-builder/scripts/connections.py +151 -151
  28. package/stack/skills/mcp-builder/scripts/evaluation.py +373 -373
  29. package/stack/skills/mcp-builder/scripts/example_evaluation.xml +22 -22
  30. package/stack/skills/mcp-builder/scripts/requirements.txt +2 -2
  31. package/stack/skills/obsidian-cli/SKILL.md +106 -106
  32. package/stack/skills/obsidian-markdown/SKILL.md +196 -196
  33. package/stack/skills/obsidian-markdown/references/CALLOUTS.md +58 -58
  34. package/stack/skills/obsidian-markdown/references/EMBEDS.md +63 -63
  35. package/stack/skills/obsidian-markdown/references/PROPERTIES.md +61 -61
  36. package/stack/skills/react-doctor/SKILL.md +19 -19
  37. package/stack/skills/skill-creator/LICENSE.txt +201 -201
  38. package/stack/skills/skill-creator/agents/analyzer.md +274 -274
  39. package/stack/skills/skill-creator/agents/comparator.md +202 -202
  40. package/stack/skills/skill-creator/agents/grader.md +223 -223
  41. package/stack/skills/skill-creator/assets/eval_review.html +146 -146
  42. package/stack/skills/skill-creator/eval-viewer/generate_review.py +471 -471
  43. package/stack/skills/skill-creator/eval-viewer/viewer.html +1325 -1325
  44. package/stack/skills/skill-creator/references/schemas.md +430 -430
  45. package/stack/skills/skill-creator/scripts/aggregate_benchmark.py +401 -401
  46. package/stack/skills/skill-creator/scripts/generate_report.py +326 -326
  47. package/stack/skills/skill-creator/scripts/improve_description.py +248 -248
  48. package/stack/skills/skill-creator/scripts/package_skill.py +136 -136
  49. package/stack/skills/skill-creator/scripts/quick_validate.py +102 -102
  50. package/stack/skills/skill-creator/scripts/run_eval.py +310 -310
  51. package/stack/skills/skill-creator/scripts/run_loop.py +332 -332
  52. package/stack/skills/skill-creator/scripts/utils.py +47 -47
  53. package/stack/skills/supabase/SKILL.md +135 -135
  54. package/stack/skills/supabase/assets/feedback-issue-template.md +17 -17
  55. package/stack/skills/supabase/references/skill-feedback.md +17 -17
  56. package/stack/skills/supabase-postgres-best-practices/SKILL.md +64 -64
  57. package/stack/skills/supabase-postgres-best-practices/references/_contributing.md +170 -170
  58. package/stack/skills/supabase-postgres-best-practices/references/_sections.md +39 -39
  59. package/stack/skills/supabase-postgres-best-practices/references/_template.md +34 -34
  60. package/stack/skills/supabase-postgres-best-practices/references/advanced-full-text-search.md +55 -55
  61. package/stack/skills/supabase-postgres-best-practices/references/advanced-jsonb-indexing.md +49 -49
  62. package/stack/skills/supabase-postgres-best-practices/references/conn-idle-timeout.md +46 -46
  63. package/stack/skills/supabase-postgres-best-practices/references/conn-limits.md +44 -44
  64. package/stack/skills/supabase-postgres-best-practices/references/conn-pooling.md +41 -41
  65. package/stack/skills/supabase-postgres-best-practices/references/conn-prepared-statements.md +46 -46
  66. package/stack/skills/supabase-postgres-best-practices/references/data-batch-inserts.md +54 -54
  67. package/stack/skills/supabase-postgres-best-practices/references/data-n-plus-one.md +53 -53
  68. package/stack/skills/supabase-postgres-best-practices/references/data-pagination.md +50 -50
  69. package/stack/skills/supabase-postgres-best-practices/references/data-upsert.md +50 -50
  70. package/stack/skills/supabase-postgres-best-practices/references/lock-advisory.md +56 -56
  71. package/stack/skills/supabase-postgres-best-practices/references/lock-deadlock-prevention.md +68 -68
  72. package/stack/skills/supabase-postgres-best-practices/references/lock-short-transactions.md +50 -50
  73. package/stack/skills/supabase-postgres-best-practices/references/lock-skip-locked.md +54 -54
  74. package/stack/skills/supabase-postgres-best-practices/references/monitor-explain-analyze.md +45 -45
  75. package/stack/skills/supabase-postgres-best-practices/references/monitor-pg-stat-statements.md +55 -55
  76. package/stack/skills/supabase-postgres-best-practices/references/monitor-vacuum-analyze.md +55 -55
  77. package/stack/skills/supabase-postgres-best-practices/references/query-composite-indexes.md +44 -44
  78. package/stack/skills/supabase-postgres-best-practices/references/query-covering-indexes.md +40 -40
  79. package/stack/skills/supabase-postgres-best-practices/references/query-index-types.md +48 -48
  80. package/stack/skills/supabase-postgres-best-practices/references/query-missing-indexes.md +43 -43
  81. package/stack/skills/supabase-postgres-best-practices/references/query-partial-indexes.md +45 -45
  82. package/stack/skills/supabase-postgres-best-practices/references/schema-constraints.md +80 -80
  83. package/stack/skills/supabase-postgres-best-practices/references/schema-data-types.md +46 -46
  84. package/stack/skills/supabase-postgres-best-practices/references/schema-foreign-key-indexes.md +59 -59
  85. package/stack/skills/supabase-postgres-best-practices/references/schema-lowercase-identifiers.md +55 -55
  86. package/stack/skills/supabase-postgres-best-practices/references/schema-partitioning.md +55 -55
  87. package/stack/skills/supabase-postgres-best-practices/references/schema-primary-keys.md +61 -61
  88. package/stack/skills/supabase-postgres-best-practices/references/security-privileges.md +54 -54
  89. package/stack/skills/supabase-postgres-best-practices/references/security-rls-basics.md +50 -50
  90. package/stack/skills/supabase-postgres-best-practices/references/security-rls-performance.md +63 -63
  91. package/stack/skills/tdd/SKILL.md +109 -109
  92. package/stack/skills/tdd/deep-modules.md +33 -33
  93. package/stack/skills/tdd/interface-design.md +31 -31
  94. package/stack/skills/tdd/mocking.md +59 -59
  95. package/stack/skills/tdd/refactoring.md +10 -10
  96. package/stack/skills/tdd/tests.md +61 -61
  97. package/stack/skills/to-issues/SKILL.md +83 -83
  98. package/stack/skills/to-prd/SKILL.md +72 -72
  99. package/upstreams.json +96 -96
@@ -0,0 +1,59 @@
1
+ ---
2
+ description: Manual read-only lean audit — resolves repo/path scope, runs a cheap scope/routing scan, launches code-simplifier always and the relevant analysts conditionally, then reports ranked lean findings.
3
+ ---
4
+
5
+ Run a manual lean audit. Your job as the main agent: determine WHAT to audit, resolve the exact repo/path scope, decide which subagents apply, and launch them in parallel.
6
+
7
+ ## 0. Determine the audit target
8
+
9
+ User input (may be empty): {{input}}
10
+
11
+ - If the input names a repo or a path → audit that repo/subtree.
12
+ - If the input is empty or ambiguous: do a quick, cheap situation scan first — current repo root (`git rev-parse --show-toplevel`), current branch (`git rev-parse --abbrev-ref HEAD`), and the most likely changed area from the user's prompt — then ASK the user what to audit before launching anything, offering only the options that actually apply.
13
+ - If the input points to a PR or a diff → stop: `/lean-audit` is not a PR review command; use `/xreview` for diffs and PRs.
14
+
15
+ ## 1. Resolve scope
16
+
17
+ - Print the chosen repo/path scope and why it was selected.
18
+ - If the input is a path, audit that subtree.
19
+ - If the input is a repo root, audit the repo from that root downward.
20
+ - If you are inside a worktree, use that worktree as the scope unless the user named a different path.
21
+
22
+ ## 2. Cheap scope/routing scan
23
+
24
+ Before launching subagents, do a quick scan for obvious routing signals in the scope:
25
+
26
+ - changed file names and top-level directories
27
+ - obvious code/test/docs boundaries
28
+ - areas that likely need code-simplifier vs analyst passes
29
+ - anything that changes which subagents should run
30
+
31
+ Use the scan to route work, not to judge bloat or rewrite anything. Code-simplifier owns the lean/anti-bloat findings.
32
+
33
+ ## 3. Launch the remaining subagents in PARALLEL
34
+
35
+ All subagents are CONDITIONAL and read-only. Launch one only when the scope indicates it applies. Pass every one EXACTLY:
36
+
37
+ - the audit scope: repo root / path root, verbatim
38
+ - the instruction: audit only that scope — never broaden it, and never apply fixes
39
+
40
+ Subagents and their triggers:
41
+
42
+ 1. Task(subagent_type='code-simplifier') — always; this is the lean/anti-bloat pass
43
+ 2. Task(subagent_type='backend-analyst') — if the scope includes backend, DB, APIs, server logic, or data flows
44
+ 3. Task(subagent_type='frontend-analyst') — if the scope includes UI, hooks, state, rendering, or client-side flows
45
+ 4. Task(subagent_type='type-design-analyzer') — if the scope changes types, interfaces, schemas, or contracts
46
+
47
+ If none of a subagent's triggers are present, skip it and note that it was skipped. Always state which subagents ran and which were skipped and why.
48
+
49
+ ## 4. Synthesize
50
+
51
+ After the relevant subagents complete, synthesize their findings into a unified report:
52
+
53
+ - Scope used and how it was chosen
54
+ - Subagents run vs skipped (with reason)
55
+ - Ranked findings: delete, stdlib, native/platform, reuse, yagni, shrink
56
+ - What should be deferred because it is out of scope or too risky for this audit
57
+ - Positive findings
58
+
59
+ Do not apply fixes. This command only audits and reports.
@@ -1,80 +1,82 @@
1
- ---
2
- description: Conditional multi-agent code review — determines what to review (asking if unclear), resolves the exact diff, and launches only the relevant subagents in parallel
3
- ---
4
-
5
- Run a comprehensive multi-agent review. Your job as the main agent: determine WHAT to review, resolve the exact diff, decide which subagents apply, and launch them in parallel.
6
-
7
- ## 0. Determine the review target
8
-
9
- User input (may be empty): {{input}}
10
-
11
- - If the input names a branch → review `git diff <that-branch>...HEAD`.
12
- - If the input references a PR (number or URL) → use that PR's base branch as BASE.
13
- - If the input names files/paths/areas → review the changes touching those paths.
14
- - If the input is empty or ambiguous: do a quick, cheap situation scan first — uncommitted changes (`git status --short`), current branch, open PR for it (`gh pr view --json baseRefName --jq .baseRefName`) — and ASK the user what to review before launching anything, offering only the options that actually apply:
15
- 1. Uncommitted work (`git diff` + `git diff --staged`)
16
- 2. The current branch against its base (say which base you detected and how)
17
- 3. Against a specific branch they name
18
- 4. An existing PR
19
- 5. Specific files or areas
20
-
21
- Do NOT guess silently: a review against the wrong target wastes every subagent and buries the user in irrelevant findings.
22
-
23
- ## 1. Resolve BASE and HEAD (branch/PR reviews)
24
-
25
- HEAD is the current branch / worktree being worked on (`git rev-parse --abbrev-ref HEAD`).
26
-
27
- BASE is the branch the work will merge into. Do NOT default to `main` — work is often done in sub-branches whose PR targets another branch. Resolve BASE in this order:
28
-
29
- 1. The branch the user chose in step 0, if any.
30
- 2. If the current branch has an open GitHub PR, its base branch (`gh pr view --json baseRefName --jq .baseRefName`).
31
- 3. Otherwise, inspect local and `origin/*` branches and choose the branch directly underneath the current branch: the candidate whose merge-base with HEAD is newest/closest to HEAD, excluding the current branch itself and its remote tracking ref.
32
- 4. If still unsure, ask the user — never silently fall back to `main`.
33
-
34
- Print the chosen BASE and HEAD and why BASE was selected. (For working-tree reviews there is no BASE: the scope is `git diff` + `git diff --staged`.)
35
-
36
- ## 2. Decide routing (lightweight)
37
-
38
- List only the changed file NAMES to decide routing — do NOT load the full diff into your own context:
39
- `git diff <BASE>...HEAD --name-only` (or `git diff --name-only` + `git diff --staged --name-only` for working-tree reviews).
40
-
41
- Sanity check: if that list is far larger than the work being reviewed (hundreds of files, unrelated areas), BASE is almost certainly wrong — STOP, re-resolve it (step 1), and only continue when the diff matches the actual work. Reviewing against the wrong BASE makes every finding worthless.
42
-
43
- ## 3. Comment pass FIRST (conditional)
44
-
45
- If the diff adds or changes comments/docstrings, run `comment-fixer` ALONE before the analysts — it edits comments in place (comments only, never code), so the analysts then review a diff already clean of comment noise instead of re-reporting it or mistaking its edits for contamination.
46
-
47
- - Pass it the same scope (BASE/HEAD or working diff) as everyone else.
48
- - If it changed anything and the scope is a committed diff (branch/PR): comment-fixer itself never commits — YOU commit its fixes to the reviewed branch before launching the analysts, staging ONLY the files it touched (never `-a`/`-A`: don't sweep unrelated working-tree changes into the commit). If the commit can't be made (branch checked out elsewhere, hook rejection), leave the edits uncommitted and say so in the report.
49
- - For working-tree reviews: leave its edits uncommitted (they join the user's pending work) and say so in the report.
50
- - If the diff touches no comments, skip it and move on.
51
-
52
- ## 4. Launch the remaining subagents in PARALLEL
53
-
54
- All subagents are CONDITIONAL: launch one only when the changed files indicate it applies. Run them in PARALLEL via the Task tool. Each subagent fetches its OWN diff; all are read-only. Pass every one EXACTLY:
55
-
56
- - the review scope: BASE and HEAD branches (verbatim), or "working diff" for uncommitted work
57
- - the instruction: review only that scope — never assume `main`, use the scope given
58
-
59
- Subagents and their triggers:
60
-
61
- 1. Task(subagent_type='test-analyzer') — only if the diff touches tests or code that should be tested
62
- 2. Task(subagent_type='silent-failure-hunter') — only if the diff includes error handling, try/catch, fallbacks, or async flows
63
- 3. Task(subagent_type='type-design-analyzer') — only if the diff changes types, interfaces, schemas, or public contracts
64
- 4. Task(subagent_type='code-reviewer') — for general code quality whenever non-trivial source code changed
65
- 5. Task(subagent_type='code-simplifier') — only if the diff introduces complexity worth simplifying
66
- 6. Task(subagent_type='security-auditor') — only if the diff touches auth, authorization, permissions, secrets/credentials, sensitive data, input validation, webhooks, or other security-critical flows
67
-
68
- If none of a subagent's triggers are present, skip it and note that it was skipped. Always state which subagents ran and which were skipped and why.
69
-
70
- ## 5. Synthesize
71
-
72
- After the relevant subagents complete, synthesize their findings into a unified report:
73
-
74
- - Review scope used (BASE/HEAD or working diff) and how it was chosen
75
- - Subagents run vs skipped (with reason)
76
- - Critical Issues (must fix)
77
- - Important Improvements (should fix)
78
- - Suggestions (nice to have)
79
- - Changes already applied (comment fixes: committed to the branch, or left uncommitted for working-tree reviews)
80
- - Positive Findings
1
+ ---
2
+ description: Conditional multi-agent code review — determines what to review (asking if unclear), resolves the exact diff, and launches only the relevant subagents in parallel
3
+ ---
4
+
5
+ Run a comprehensive multi-agent review. Your job as the main agent: determine WHAT to review, resolve the exact diff, decide which subagents apply, and launch them in parallel.
6
+
7
+ ## 0. Determine the review target
8
+
9
+ User input (may be empty): {{input}}
10
+
11
+ - If the input names a branch → review `git diff <that-branch>...HEAD`.
12
+ - If the input references a PR (number or URL) → use that PR's base branch as BASE.
13
+ - If the input names files/paths/areas → review the changes touching those paths.
14
+ - If the input is empty or ambiguous: do a quick, cheap situation scan first — uncommitted changes (`git status --short`), current branch, open PR for it (`gh pr view --json baseRefName --jq .baseRefName`) — and ASK the user what to review before launching anything, offering only the options that actually apply:
15
+ 1. Uncommitted work (`git diff` + `git diff --staged`)
16
+ 2. The current branch against its base (say which base you detected and how)
17
+ 3. Against a specific branch they name
18
+ 4. An existing PR
19
+ 5. Specific files or areas
20
+
21
+ Do NOT guess silently: a review against the wrong target wastes every subagent and buries the user in irrelevant findings.
22
+
23
+ ## 1. Resolve BASE and HEAD (branch/PR reviews)
24
+
25
+ HEAD is the current branch / worktree being worked on (`git rev-parse --abbrev-ref HEAD`).
26
+
27
+ BASE is the branch the work will merge into. Do NOT default to `main` — work is often done in sub-branches whose PR targets another branch. Resolve BASE in this order:
28
+
29
+ 1. The branch the user chose in step 0, if any.
30
+ 2. If the current branch has an open GitHub PR, its base branch (`gh pr view --json baseRefName --jq .baseRefName`).
31
+ 3. Otherwise, inspect local and `origin/*` branches and choose the branch directly underneath the current branch: the candidate whose merge-base with HEAD is newest/closest to HEAD, excluding the current branch itself and its remote tracking ref.
32
+ 4. If still unsure, ask the user — never silently fall back to `main`.
33
+
34
+ Print the chosen BASE and HEAD and why BASE was selected. (For working-tree reviews there is no BASE: the scope is `git diff` + `git diff --staged`.)
35
+
36
+ ## 2. Decide routing (lightweight)
37
+
38
+ List only the changed file NAMES to decide routing — do NOT load the full diff into your own context:
39
+ `git diff <BASE>...HEAD --name-only` (or `git diff --name-only` + `git diff --staged --name-only` for working-tree reviews).
40
+
41
+ Sanity check: if that list is far larger than the work being reviewed (hundreds of files, unrelated areas), BASE is almost certainly wrong — STOP, re-resolve it (step 1), and only continue when the diff matches the actual work. Reviewing against the wrong BASE makes every finding worthless.
42
+
43
+ ## 3. Comment pass FIRST (conditional)
44
+
45
+ If the diff adds or changes comments/docstrings, run `comment-fixer` ALONE before the analysts — it edits comments in place (comments only, never code), so the analysts then review a diff already clean of comment noise instead of re-reporting it or mistaking its edits for contamination.
46
+
47
+ - Pass it the same scope (BASE/HEAD or working diff) as everyone else.
48
+ - If it changed anything and the scope is a committed diff (branch/PR): comment-fixer itself never commits — YOU commit its fixes to the reviewed branch before launching the analysts, staging ONLY the files it touched (never `-a`/`-A`: don't sweep unrelated working-tree changes into the commit). If the commit can't be made (branch checked out elsewhere, hook rejection), leave the edits uncommitted and say so in the report.
49
+ - For working-tree reviews: leave its edits uncommitted (they join the user's pending work) and say so in the report.
50
+ - If the diff touches no comments, skip it and move on.
51
+
52
+ ## 4. Launch the remaining subagents in PARALLEL
53
+
54
+ All subagents are CONDITIONAL: launch one only when the changed files indicate it applies. Run them in PARALLEL via the Task tool. Each subagent fetches its OWN diff; all are read-only. Pass every one EXACTLY:
55
+
56
+ - the review scope: BASE and HEAD branches (verbatim), or "working diff" for uncommitted work
57
+ - the instruction: review only that scope — never assume `main`, use the scope given
58
+
59
+ Subagents and their triggers:
60
+
61
+ 1. Task(subagent_type='test-analyzer') — only if the diff touches tests or code that should be tested
62
+ 2. Task(subagent_type='silent-failure-hunter') — only if the diff includes error handling, try/catch, fallbacks, or async flows
63
+ 3. Task(subagent_type='type-design-analyzer') — only if the diff changes types, interfaces, schemas, or public contracts
64
+ 4. Task(subagent_type='code-reviewer') — for general code quality whenever non-trivial source code changed
65
+ 5. Task(subagent_type='code-simplifier') — only if the diff introduces complexity worth simplifying; this is the lean/anti-bloat pass for diffs and PRs
66
+ 6. Task(subagent_type='security-auditor') — only if the diff touches auth, authorization, permissions, secrets/credentials, sensitive data, input validation, webhooks, or other security-critical flows
67
+
68
+ If none of a subagent's triggers are present, skip it and note that it was skipped. Always state which subagents ran and which were skipped and why.
69
+
70
+ `/lean-audit` is a separate manual repo/path command, not post-PR automation. Do not route it from here.
71
+
72
+ ## 5. Synthesize
73
+
74
+ After the relevant subagents complete, synthesize their findings into a unified report. Use 4R internally (Reliability / Resilience / Readability / Risk) as a checklist while synthesizing; do not add a separate 4R section or taxonomy to the final report.
75
+
76
+ - Review scope used (BASE/HEAD or working diff) and how it was chosen
77
+ - Subagents run vs skipped (with reason)
78
+ - Critical Issues (must fix)
79
+ - Important Improvements (should fix)
80
+ - Suggestions (nice to have)
81
+ - Changes already applied (comment fixes: committed to the branch, or left uncommitted for working-tree reviews)
82
+ - Positive Findings
@@ -1,18 +1,18 @@
1
- {
2
- "$comment": "Hooks canónicos del stack. Formato base = Claude Code (code.claude.com/docs/en/hooks). Traducción por adapter en install: Claude Code → merge en ~/.claude/settings.json (clave hooks) · Codex → ~/.codex/hooks.json (el usuario debe aprobarlos después con /hooks) · OpenCode → plugin puente stack/plugins/opencode/hooks.ts con su propio hooks.json. Extensión propia 'x-command-includes': filtro por substring del comando bash que el puente de OpenCode aplica antes de ejecutar el script; en Claude Code y Codex el filtro lo aplica el propio script (sale con exit 0 si el comando no aplica). El placeholder {{SCRIPTS_DIR}} lo resuelve el instalador a la ruta real donde queden instalados los scripts del stack.",
3
- "hooks": {
4
- "PostToolUse": [
5
- {
6
- "matcher": "Bash|PowerShell",
7
- "x-command-includes": "gh pr create",
8
- "hooks": [
9
- {
10
- "type": "command",
11
- "command": "node \"{{SCRIPTS_DIR}}/post-pr-review.cjs\"",
12
- "timeout": 30
13
- }
14
- ]
15
- }
16
- ]
17
- }
18
- }
1
+ {
2
+ "$comment": "Hooks canónicos del stack. Formato base = Claude Code (code.claude.com/docs/en/hooks). Traducción por adapter en install: Claude Code → merge en ~/.claude/settings.json (clave hooks) · Codex → ~/.codex/hooks.json (el usuario debe aprobarlos después con /hooks) · OpenCode → plugin puente stack/plugins/opencode/hooks.ts con su propio hooks.json. Extensión propia 'x-command-includes': filtro por substring del comando bash que el puente de OpenCode aplica antes de ejecutar el script; en Claude Code y Codex el filtro lo aplica el propio script (sale con exit 0 si el comando no aplica). El placeholder {{SCRIPTS_DIR}} lo resuelve el instalador a la ruta real donde queden instalados los scripts del stack.",
3
+ "hooks": {
4
+ "PostToolUse": [
5
+ {
6
+ "matcher": "Bash|PowerShell",
7
+ "x-command-includes": "gh pr create",
8
+ "hooks": [
9
+ {
10
+ "type": "command",
11
+ "command": "node \"{{SCRIPTS_DIR}}/post-pr-review.cjs\"",
12
+ "timeout": 30
13
+ }
14
+ ]
15
+ }
16
+ ]
17
+ }
18
+ }
@@ -1,156 +1,159 @@
1
- #!/usr/bin/env node
2
- /**
3
- * Global PostToolUse hook: gh pr create
4
- *
5
- * Injects a conditional multi-agent review request after a PR is created.
6
- * Generic and project-agnostic: no version bump, no React Doctor, no project paths.
7
- *
8
- * The review subagents are CONDITIONAL — only the ones relevant to the diff run.
9
- * Mirrors the `/xreview` command logic so both stay aligned: comment-fixer first
10
- * (committed before the analysts), then the read-only analysts in parallel.
11
- *
12
- * Payload compatibility (stdin JSON), so the same script works on every runtime:
13
- * - Claude Code hooks: { tool_name: "Bash", tool_input: { command: "..." }, cwd }
14
- * - Codex hooks: { tool_name: "shell", tool_input: { command: [...] }, cwd }
15
- * - OpenCode bridge: { tool: "bash", args: { command: "..." }, directory }
16
- *
17
- * Output (single channel per runtime, so the bridge never duplicates it):
18
- * - OpenCode bridge payload → plain message on stderr.
19
- * - Claude Code / Codex payload JSON additionalContext on stdout.
20
- * Exit 0 always.
21
- */
22
-
23
- const { execSync } = require('child_process');
24
- const path = require('path');
25
-
26
- const DEFAULT_BASE_BRANCH = 'main';
27
- const BASE_BRANCH_SOURCE = Object.freeze({
28
- GH: 'gh',
29
- ORIGIN_HEAD: 'origin-head',
30
- DEFAULT: 'default',
31
- });
32
-
33
- function writeWarning(message) {
34
- process.stderr.write(`post-pr-review: warning: ${message}\n`);
35
- }
36
-
37
- function formatGitRef(value) {
38
- const ref = String(value);
39
- return /^[A-Za-z0-9._/-]+$/.test(ref) ? ref : `'${ref.replace(/'/g, "'\\''")}'`;
40
- }
41
-
42
- function resolveBaseBranch(cwd) {
43
- try {
44
- const base = execSync('gh pr view --json baseRefName --jq .baseRefName', {
45
- cwd,
46
- encoding: 'utf8',
47
- stdio: ['ignore', 'pipe', 'ignore'],
48
- timeout: 8_000,
49
- }).trim();
50
- if (base) return { branch: base, source: BASE_BRANCH_SOURCE.GH };
51
- } catch {
52
- // PR not yet discoverable; fall back below.
53
- }
54
-
55
- try {
56
- const originHead = execSync('git symbolic-ref refs/remotes/origin/HEAD', {
57
- cwd,
58
- encoding: 'utf8',
59
- stdio: ['ignore', 'pipe', 'ignore'],
60
- timeout: 10_000,
61
- }).trim();
62
- if (originHead) {
63
- return {
64
- branch: originHead.replace(/^refs\/remotes\/origin\//, ''),
65
- source: BASE_BRANCH_SOURCE.ORIGIN_HEAD,
66
- };
67
- }
68
- } catch {
69
- // ignore
70
- }
71
-
72
- return { branch: DEFAULT_BASE_BRANCH, source: BASE_BRANCH_SOURCE.DEFAULT };
73
- }
74
-
75
- let raw = '';
76
- process.stdin.setEncoding('utf8');
77
- process.stdin.on('data', (chunk) => (raw += chunk));
78
- process.stdin.on('end', () => {
79
- let data = {};
80
- try {
81
- data = JSON.parse(raw || '{}');
82
- } catch {
83
- writeWarning('invalid JSON payload; skipping review hook.');
84
- process.exit(0);
85
- }
86
-
87
- const toolName = String(data.tool_name || data.tool || '').toLowerCase();
88
- const SHELL_TOOLS = ['bash', 'shell', 'local_shell', 'powershell'];
89
- const commandValue = data?.tool_input?.command ?? data?.args?.command ?? '';
90
- // Codex passes the shell command as an argv array; the rest as a string.
91
- const rawToolCommand = Array.isArray(commandValue) ? commandValue.join(' ') : String(commandValue);
92
- const toolCommand = rawToolCommand.toLowerCase();
93
-
94
- if (!SHELL_TOOLS.includes(toolName) || !toolCommand.includes('gh pr create')) {
95
- process.exit(0);
96
- }
97
-
98
- const scriptDir = __dirname;
99
- const projectDir = data.cwd || data.directory || path.resolve(scriptDir, '..');
100
- const resolution = resolveBaseBranch(projectDir);
101
- const baseBranch = resolution.branch;
102
- const baseRef = formatGitRef(baseBranch);
103
- const diffScope = `git diff ${baseRef}...HEAD`;
104
- const isConfirmed = resolution.source === BASE_BRANCH_SOURCE.GH;
105
- const baseSummary = isConfirmed
106
- ? `BASE (PR target, confirmed via gh pr view): ${baseBranch}`
107
- : `BASE (PR target, NOT confirmed — fallback guess): ${baseBranch}. Before anything else, re-resolve it yourself: run \`gh pr view --json baseRefName --jq .baseRefName\` (the PR exists now; this hook may have raced its creation) and use THAT as BASE. Keep ${baseBranch} only if it still fails. Work is often done in sub-branches whose PR does NOT target the default branch — reviewing against the wrong BASE produces a huge, useless diff.`;
108
-
109
- const message = `<post-pr-review-required>
110
- A PR was just created. Run a conditional multi-agent review BEFORE reporting back to the user.
111
-
112
- ${baseSummary}
113
- HEAD: the current branch / worktree (resolve with \`git rev-parse --abbrev-ref HEAD\`).
114
-
115
- 1. Routing only (lightweight): list changed file NAMES with \`${diffScope} --name-only\` to decide which subagents apply. Do NOT load the full diff into your own context.
116
-
117
- Sanity check: if that list is far larger than the work just done (hundreds of files, unrelated areas), BASE is almost certainly wrong STOP, re-resolve the PR base with \`gh pr view\`, and only continue when the diff matches the actual work.
118
-
119
- 2. Comment pass FIRST (conditional): if the diff adds or changes comments/docstrings, run comment-fixer ALONE before the analysts it edits comments in place (comments only, never code). If it changed anything, comment-fixer itself never commits — YOU commit its fixes to the PR branch BEFORE launching the analysts, staging ONLY the files it touched (never -a/-A: don't sweep unrelated working-tree changes), so the diff they fetch is already clean of comment noise; push them together with whatever the review produces, or on their own if nothing else needs fixing. If the commit can't be made, leave the edits uncommitted and say so in the report. If the diff touches no comments, skip it.
120
-
121
- 3. The remaining subagents are CONDITIONAL, read-only, and each fetches its OWN diff. Launch in PARALLEL (with your runtime's delegation mechanism) ONLY the relevant ones, passing each EXACTLY the BASE and HEAD branches and the instruction: review only \`${diffScope}\` never assume \`main\`, use the BASE/HEAD given.
122
- - test-analyzer — only if the diff touches tests or code that should be tested
123
- - silent-failure-hunter only if the diff includes error handling, try/catch, fallbacks, or async flows
124
- - type-design-analyzer — only if the diff changes types, interfaces, schemas, or public contracts
125
- - code-reviewerfor general code quality whenever non-trivial source code changed
126
- - code-simplifier — only if the diff introduces complexity worth simplifying
127
- - security-auditoronly if the diff touches auth, authorization, permissions, secrets/credentials, sensitive data, input validation, webhooks, or other security-critical flows
128
-
129
- If none of a subagent's triggers are present, skip it. Always state which subagents ran and which were skipped and why.
130
-
131
- 4. After the relevant subagents complete, synthesize a unified report:
132
- - BASE and HEAD used
133
- - Subagents run vs skipped (with reason)
134
- - Critical Issues (must fix)
135
- - Important Improvements (should fix)
136
- - Suggestions (nice to have)
137
- - Changes already applied (comment fixes: committed to the PR branch, or left uncommitted for working-tree reviews)
138
- - Positive Findings
139
- </post-pr-review-required>`;
140
-
141
- // Un solo canal por runtime: el bridge de OpenCode recoge stdout Y stderr,
142
- // así que emitir por ambos duplicaría el mensaje.
143
- const isOpenCodeBridge = data.tool !== undefined && data.tool_name === undefined;
144
- if (isOpenCodeBridge) {
145
- process.stderr.write(message + '\n');
146
- } else {
147
- // Claude Code / Codex PostToolUse leen additionalContext del stdout JSON.
148
- process.stdout.write(
149
- JSON.stringify({
150
- additionalContext: message,
151
- hookSpecificOutput: { hookEventName: 'PostToolUse', additionalContext: message },
152
- }) + '\n',
153
- );
154
- }
155
- process.exit(0);
156
- });
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Global PostToolUse hook: gh pr create
4
+ *
5
+ * Injects a conditional multi-agent review request after a PR is created.
6
+ * Generic and project-agnostic: no version bump, no React Doctor, no project paths.
7
+ *
8
+ * The review subagents are CONDITIONAL — only the ones relevant to the diff run.
9
+ * Mirrors the `/xreview` command logic so both stay aligned: comment-fixer first
10
+ * (committed before the analysts), then the read-only analysts in parallel. 4R
11
+ * stays internal (Reliability / Resilience / Readability / Risk), not a separate
12
+ * report section, taxonomy, or extra agents.
13
+ *
14
+ * Payload compatibility (stdin JSON), so the same script works on every runtime:
15
+ * - Claude Code hooks: { tool_name: "Bash", tool_input: { command: "..." }, cwd }
16
+ * - Codex hooks: { tool_name: "shell", tool_input: { command: [...] }, cwd }
17
+ * - OpenCode bridge: { tool: "bash", args: { command: "..." }, directory }
18
+ *
19
+ * Output (single channel per runtime, so the bridge never duplicates it):
20
+ * - OpenCode bridge payload → plain message on stderr.
21
+ * - Claude Code / Codex payload → JSON additionalContext on stdout.
22
+ * Exit 0 always.
23
+ */
24
+
25
+ const { execSync } = require('child_process');
26
+ const path = require('path');
27
+
28
+ const DEFAULT_BASE_BRANCH = 'main';
29
+ const BASE_BRANCH_SOURCE = Object.freeze({
30
+ GH: 'gh',
31
+ ORIGIN_HEAD: 'origin-head',
32
+ DEFAULT: 'default',
33
+ });
34
+
35
+ function writeWarning(message) {
36
+ process.stderr.write(`post-pr-review: warning: ${message}\n`);
37
+ }
38
+
39
+ function formatGitRef(value) {
40
+ const ref = String(value);
41
+ return /^[A-Za-z0-9._/-]+$/.test(ref) ? ref : `'${ref.replace(/'/g, "'\\''")}'`;
42
+ }
43
+
44
+ function resolveBaseBranch(cwd) {
45
+ try {
46
+ const base = execSync('gh pr view --json baseRefName --jq .baseRefName', {
47
+ cwd,
48
+ encoding: 'utf8',
49
+ stdio: ['ignore', 'pipe', 'ignore'],
50
+ timeout: 8_000,
51
+ }).trim();
52
+ if (base) return { branch: base, source: BASE_BRANCH_SOURCE.GH };
53
+ } catch {
54
+ // PR not yet discoverable; fall back below.
55
+ }
56
+
57
+ try {
58
+ const originHead = execSync('git symbolic-ref refs/remotes/origin/HEAD', {
59
+ cwd,
60
+ encoding: 'utf8',
61
+ stdio: ['ignore', 'pipe', 'ignore'],
62
+ timeout: 10_000,
63
+ }).trim();
64
+ if (originHead) {
65
+ return {
66
+ branch: originHead.replace(/^refs\/remotes\/origin\//, ''),
67
+ source: BASE_BRANCH_SOURCE.ORIGIN_HEAD,
68
+ };
69
+ }
70
+ } catch {
71
+ // ignore
72
+ }
73
+
74
+ return { branch: DEFAULT_BASE_BRANCH, source: BASE_BRANCH_SOURCE.DEFAULT };
75
+ }
76
+
77
+ let raw = '';
78
+ process.stdin.setEncoding('utf8');
79
+ process.stdin.on('data', (chunk) => (raw += chunk));
80
+ process.stdin.on('end', () => {
81
+ let data = {};
82
+ try {
83
+ data = JSON.parse(raw || '{}');
84
+ } catch {
85
+ writeWarning('invalid JSON payload; skipping review hook.');
86
+ process.exit(0);
87
+ }
88
+
89
+ const toolName = String(data.tool_name || data.tool || '').toLowerCase();
90
+ const SHELL_TOOLS = ['bash', 'shell', 'local_shell', 'powershell'];
91
+ const commandValue = data?.tool_input?.command ?? data?.args?.command ?? '';
92
+ // Codex passes the shell command as an argv array; the rest as a string.
93
+ const rawToolCommand = Array.isArray(commandValue) ? commandValue.join(' ') : String(commandValue);
94
+ const toolCommand = rawToolCommand.toLowerCase();
95
+
96
+ if (!SHELL_TOOLS.includes(toolName) || !toolCommand.includes('gh pr create')) {
97
+ process.exit(0);
98
+ }
99
+
100
+ const scriptDir = __dirname;
101
+ const projectDir = data.cwd || data.directory || path.resolve(scriptDir, '..');
102
+ const resolution = resolveBaseBranch(projectDir);
103
+ const baseBranch = resolution.branch;
104
+ const baseRef = formatGitRef(baseBranch);
105
+ const diffScope = `git diff ${baseRef}...HEAD`;
106
+ const isConfirmed = resolution.source === BASE_BRANCH_SOURCE.GH;
107
+ const baseSummary = isConfirmed
108
+ ? `BASE (PR target, confirmed via gh pr view): ${baseBranch}`
109
+ : `BASE (PR target, NOT confirmed — fallback guess): ${baseBranch}. Before anything else, re-resolve it yourself: run \`gh pr view --json baseRefName --jq .baseRefName\` (the PR exists now; this hook may have raced its creation) and use THAT as BASE. Keep ${baseBranch} only if it still fails. Work is often done in sub-branches whose PR does NOT target the default branch — reviewing against the wrong BASE produces a huge, useless diff.`;
110
+
111
+ const message = `<post-pr-review-required>
112
+ A PR was just created. Run a conditional multi-agent review BEFORE reporting back to the user.
113
+
114
+ ${baseSummary}
115
+ HEAD: the current branch / worktree (resolve with \`git rev-parse --abbrev-ref HEAD\`).
116
+
117
+ 1. Routing only (lightweight): list changed file NAMES with \`${diffScope} --name-only\` to decide which subagents apply. Do NOT load the full diff into your own context.
118
+
119
+ Sanity check: if that list is far larger than the work just done (hundreds of files, unrelated areas), BASE is almost certainly wrong STOP, re-resolve the PR base with \`gh pr view\`, and only continue when the diff matches the actual work.
120
+
121
+ 2. Comment pass FIRST (conditional): if the diff adds or changes comments/docstrings, run comment-fixer ALONE before the analysts — it edits comments in place (comments only, never code). If it changed anything, comment-fixer itself never commits — YOU commit its fixes to the PR branch BEFORE launching the analysts, staging ONLY the files it touched (never -a/-A: don't sweep unrelated working-tree changes), so the diff they fetch is already clean of comment noise; push them together with whatever the review produces, or on their own if nothing else needs fixing. If the commit can't be made, leave the edits uncommitted and say so in the report. If the diff touches no comments, skip it.
122
+
123
+ 3. The remaining subagents are CONDITIONAL, read-only, and each fetches its OWN diff. Launch in PARALLEL (with your runtime's delegation mechanism) ONLY the relevant ones, passing each EXACTLY the BASE and HEAD branches and the instruction: review only \`${diffScope}\` — never assume \`main\`, use the BASE/HEAD given.
124
+ - test-analyzer — only if the diff touches tests or code that should be tested
125
+ - silent-failure-hunteronly if the diff includes error handling, try/catch, fallbacks, or async flows
126
+ - type-design-analyzer — only if the diff changes types, interfaces, schemas, or public contracts
127
+ - code-reviewerfor general code quality whenever non-trivial source code changed
128
+ - code-simplifier — only if the diff introduces complexity worth simplifying; this is the lean/anti-bloat pass for diffs and PRs
129
+ - security-auditor only if the diff touches auth, authorization, permissions, secrets/credentials, sensitive data, input validation, webhooks, or other security-critical flows
130
+
131
+ If none of a subagent's triggers are present, skip it. Always state which subagents ran and which were skipped and why.
132
+
133
+ 4. After the relevant subagents complete, synthesize a unified report:
134
+ Use 4R internally (Reliability / Resilience / Readability / Risk) as a checklist while synthesizing; do not add a separate 4R section or taxonomy to the final report.
135
+ - BASE and HEAD used
136
+ - Subagents run vs skipped (with reason)
137
+ - Critical Issues (must fix)
138
+ - Important Improvements (should fix)
139
+ - Suggestions (nice to have)
140
+ - Changes already applied (comment fixes: committed to the PR branch, or left uncommitted for working-tree reviews)
141
+ - Positive Findings
142
+ </post-pr-review-required>`;
143
+
144
+ // Un solo canal por runtime: el bridge de OpenCode recoge stdout Y stderr,
145
+ // así que emitir por ambos duplicaría el mensaje.
146
+ const isOpenCodeBridge = data.tool !== undefined && data.tool_name === undefined;
147
+ if (isOpenCodeBridge) {
148
+ process.stderr.write(message + '\n');
149
+ } else {
150
+ // Claude Code / Codex PostToolUse leen additionalContext del stdout JSON.
151
+ process.stdout.write(
152
+ JSON.stringify({
153
+ additionalContext: message,
154
+ hookSpecificOutput: { hookEventName: 'PostToolUse', additionalContext: message },
155
+ }) + '\n',
156
+ );
157
+ }
158
+ process.exit(0);
159
+ });