@wrongstack/plugins 0.293.0 → 0.295.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.
Files changed (189) hide show
  1. package/README.md +7 -71
  2. package/dist/accessibility-auditor/index.d.ts +1 -1
  3. package/dist/accessibility-auditor/index.d.ts.map +1 -1
  4. package/dist/accessibility-auditor.js +31 -31
  5. package/dist/agent-handoff/index.d.ts +1 -1
  6. package/dist/agent-handoff/index.d.ts.map +1 -1
  7. package/dist/api-compatibility-gate/index.d.ts +1 -1
  8. package/dist/api-compatibility-gate/index.d.ts.map +1 -1
  9. package/dist/api-compatibility-gate.js +21 -16
  10. package/dist/audit/index.d.ts +386 -0
  11. package/dist/audit/index.d.ts.map +1 -0
  12. package/dist/audit.d.ts +1 -0
  13. package/dist/audit.js +454 -0
  14. package/dist/auto-doc/index.d.ts +1 -1
  15. package/dist/auto-doc/index.d.ts.map +1 -1
  16. package/dist/auto-escalate/index.d.ts +1 -1
  17. package/dist/auto-escalate/index.d.ts.map +1 -1
  18. package/dist/auto-i18n-extractor/index.d.ts +1 -1
  19. package/dist/auto-i18n-extractor/index.d.ts.map +1 -1
  20. package/dist/auto-i18n-extractor.js +2 -1
  21. package/dist/branch-guard/index.d.ts +1 -1
  22. package/dist/branch-guard/index.d.ts.map +1 -1
  23. package/dist/branch-guard.js +9 -1
  24. package/dist/catalog.d.ts +5 -30
  25. package/dist/catalog.d.ts.map +1 -1
  26. package/dist/changelog-writer/index.d.ts +1 -1
  27. package/dist/changelog-writer/index.d.ts.map +1 -1
  28. package/dist/checkpoint/index.d.ts +1 -1
  29. package/dist/checkpoint/index.d.ts.map +1 -1
  30. package/dist/checkpoint.js +7 -8
  31. package/dist/code-metrics/index.d.ts +1 -1
  32. package/dist/code-metrics/index.d.ts.map +1 -1
  33. package/dist/code-metrics.js +29 -29
  34. package/dist/commit-validator/index.d.ts +1 -1
  35. package/dist/commit-validator/index.d.ts.map +1 -1
  36. package/dist/config-validator/index.d.ts +1 -1
  37. package/dist/config-validator/index.d.ts.map +1 -1
  38. package/dist/context-pins/index.d.ts +1 -1
  39. package/dist/context-pins/index.d.ts.map +1 -1
  40. package/dist/cost-tracker/index.d.ts +1 -1
  41. package/dist/cost-tracker/index.d.ts.map +1 -1
  42. package/dist/cost-tracker.js +9 -2
  43. package/dist/cron/index.d.ts +1 -1
  44. package/dist/cron/index.d.ts.map +1 -1
  45. package/dist/dead-code-detector/index.d.ts +1 -1
  46. package/dist/dead-code-detector/index.d.ts.map +1 -1
  47. package/dist/dead-code-detector.js +26 -18
  48. package/dist/dep-guard/index.d.ts +1 -1
  49. package/dist/dep-guard/index.d.ts.map +1 -1
  50. package/dist/dependency-vulnerability-gate/index.d.ts +1 -1
  51. package/dist/dependency-vulnerability-gate/index.d.ts.map +1 -1
  52. package/dist/dependency-vulnerability-gate.js +34 -22
  53. package/dist/diff-summary/index.d.ts +1 -1
  54. package/dist/diff-summary/index.d.ts.map +1 -1
  55. package/dist/diff-summary.js +28 -29
  56. package/dist/doc-sync-guard/index.d.ts +1 -1
  57. package/dist/doc-sync-guard/index.d.ts.map +1 -1
  58. package/dist/doc-sync-guard.js +2 -1
  59. package/dist/duplicate-code-detector/index.d.ts +26 -1
  60. package/dist/duplicate-code-detector/index.d.ts.map +1 -1
  61. package/dist/duplicate-code-detector.js +178 -67
  62. package/dist/error-lens/index.d.ts +1 -1
  63. package/dist/error-lens/index.d.ts.map +1 -1
  64. package/dist/factories/index.d.ts +4 -0
  65. package/dist/factories/index.d.ts.map +1 -0
  66. package/dist/factories.d.ts +1 -0
  67. package/dist/factories.js +74 -0
  68. package/dist/feature-flag-tracker/index.d.ts +1 -1
  69. package/dist/feature-flag-tracker/index.d.ts.map +1 -1
  70. package/dist/feature-flag-tracker.js +29 -29
  71. package/dist/file-watcher/index.d.ts +1 -1
  72. package/dist/file-watcher/index.d.ts.map +1 -1
  73. package/dist/format-on-save/index.d.ts +1 -1
  74. package/dist/format-on-save/index.d.ts.map +1 -1
  75. package/dist/format-on-save.js +2 -1
  76. package/dist/generated-plugin-exports.d.ts +65 -0
  77. package/dist/generated-plugin-exports.d.ts.map +1 -0
  78. package/dist/git-autocommit/index.d.ts +1 -1
  79. package/dist/git-autocommit/index.d.ts.map +1 -1
  80. package/dist/import-organizer/index.d.ts +1 -1
  81. package/dist/import-organizer/index.d.ts.map +1 -1
  82. package/dist/import-organizer.js +2 -1
  83. package/dist/index.d.ts +4 -183
  84. package/dist/index.d.ts.map +1 -1
  85. package/dist/index.js +17675 -17377
  86. package/dist/injection-shield/index.d.ts +1 -1
  87. package/dist/injection-shield/index.d.ts.map +1 -1
  88. package/dist/interface-contract-guard/index.d.ts +1 -1
  89. package/dist/interface-contract-guard/index.d.ts.map +1 -1
  90. package/dist/interface-contract-guard.js +29 -29
  91. package/dist/knowledge-graph/index.d.ts +1 -1
  92. package/dist/knowledge-graph/index.d.ts.map +1 -1
  93. package/dist/license-audit-gate/index.d.ts +1 -1
  94. package/dist/license-audit-gate/index.d.ts.map +1 -1
  95. package/dist/lint-gate/index.d.ts +1 -1
  96. package/dist/lint-gate/index.d.ts.map +1 -1
  97. package/dist/lint-gate.js +10 -1
  98. package/dist/llm-cache/index.d.ts +5 -1
  99. package/dist/llm-cache/index.d.ts.map +1 -1
  100. package/dist/llm-cache.js +16 -8
  101. package/dist/loop-breaker/index.d.ts +1 -1
  102. package/dist/loop-breaker/index.d.ts.map +1 -1
  103. package/dist/loop-breaker.js +10 -4
  104. package/dist/manifest/index.d.ts +16 -0
  105. package/dist/manifest/index.d.ts.map +1 -0
  106. package/dist/manifest.d.ts +1 -0
  107. package/dist/manifest.js +152 -0
  108. package/dist/migration-planner/index.d.ts +1 -1
  109. package/dist/migration-planner/index.d.ts.map +1 -1
  110. package/dist/migration-planner.js +2 -1
  111. package/dist/model-router/index.d.ts +1 -1
  112. package/dist/model-router/index.d.ts.map +1 -1
  113. package/dist/notify-hub/index.d.ts +1 -1
  114. package/dist/notify-hub/index.d.ts.map +1 -1
  115. package/dist/notify-hub/webhook-channel.d.ts +1 -1
  116. package/dist/notify-hub/webhook-channel.d.ts.map +1 -1
  117. package/dist/path-guard/index.d.ts +1 -1
  118. package/dist/path-guard/index.d.ts.map +1 -1
  119. package/dist/performance-regression-gate/index.d.ts +1 -1
  120. package/dist/performance-regression-gate/index.d.ts.map +1 -1
  121. package/dist/plugin-stack-observer/index.d.ts +1 -1
  122. package/dist/plugin-stack-observer/index.d.ts.map +1 -1
  123. package/dist/pr-drafter/index.d.ts +1 -1
  124. package/dist/pr-drafter/index.d.ts.map +1 -1
  125. package/dist/pr-drafter.js +28 -29
  126. package/dist/process-guard/index.d.ts +1 -1
  127. package/dist/process-guard/index.d.ts.map +1 -1
  128. package/dist/prompt-firewall/index.d.ts +1 -1
  129. package/dist/prompt-firewall/index.d.ts.map +1 -1
  130. package/dist/refactor-suggester/index.d.ts +1 -1
  131. package/dist/refactor-suggester/index.d.ts.map +1 -1
  132. package/dist/refactor-suggester.js +29 -29
  133. package/dist/release-notes-generator/index.d.ts +1 -1
  134. package/dist/release-notes-generator/index.d.ts.map +1 -1
  135. package/dist/release-notes-generator.js +29 -22
  136. package/dist/runtime/index.d.ts +15 -0
  137. package/dist/runtime/index.d.ts.map +1 -1
  138. package/dist/runtime/llm.d.ts +1 -1
  139. package/dist/runtime/llm.d.ts.map +1 -1
  140. package/dist/runtime.js +43 -2
  141. package/dist/schema-evolution-guard/index.d.ts +1 -1
  142. package/dist/schema-evolution-guard/index.d.ts.map +1 -1
  143. package/dist/schema-evolution-guard.js +2 -1
  144. package/dist/secret-scanner/index.d.ts +1 -1
  145. package/dist/secret-scanner/index.d.ts.map +1 -1
  146. package/dist/secret-scanner.js +7 -1
  147. package/dist/security-hotspot-scanner/index.d.ts +1 -1
  148. package/dist/security-hotspot-scanner/index.d.ts.map +1 -1
  149. package/dist/security-hotspot-scanner.js +26 -19
  150. package/dist/semantic-search-indexer/index.d.ts +1 -1
  151. package/dist/semantic-search-indexer/index.d.ts.map +1 -1
  152. package/dist/semver-bump/index.d.ts +1 -1
  153. package/dist/semver-bump/index.d.ts.map +1 -1
  154. package/dist/semver-bump.js +78 -43
  155. package/dist/session-recap/index.d.ts +1 -1
  156. package/dist/session-recap/index.d.ts.map +1 -1
  157. package/dist/shell-check/index.d.ts +1 -1
  158. package/dist/shell-check/index.d.ts.map +1 -1
  159. package/dist/smart-rename/index.d.ts +1 -1
  160. package/dist/smart-rename/index.d.ts.map +1 -1
  161. package/dist/spec-linker/index.d.ts +1 -1
  162. package/dist/spec-linker/index.d.ts.map +1 -1
  163. package/dist/spec-linker.js +222 -20772
  164. package/dist/template-engine/index.d.ts +1 -1
  165. package/dist/template-engine/index.d.ts.map +1 -1
  166. package/dist/template-engine.js +4 -6
  167. package/dist/test-coverage-gate/index.d.ts +1 -1
  168. package/dist/test-coverage-gate/index.d.ts.map +1 -1
  169. package/dist/test-coverage-gate.js +29 -14
  170. package/dist/test-flake-detector/index.d.ts +1 -1
  171. package/dist/test-flake-detector/index.d.ts.map +1 -1
  172. package/dist/test-flake-detector.js +31 -20
  173. package/dist/test-generator/index.d.ts +1 -1
  174. package/dist/test-generator/index.d.ts.map +1 -1
  175. package/dist/test-runner-gate/index.d.ts +1 -1
  176. package/dist/test-runner-gate/index.d.ts.map +1 -1
  177. package/dist/test-runner-gate.js +2 -1
  178. package/dist/todo-listener/index.d.ts +1 -32
  179. package/dist/todo-listener/index.d.ts.map +1 -1
  180. package/dist/todo-tracker/index.d.ts +1 -1
  181. package/dist/todo-tracker/index.d.ts.map +1 -1
  182. package/dist/token-budget/index.d.ts +1 -1
  183. package/dist/token-budget/index.d.ts.map +1 -1
  184. package/dist/token-throttle/index.d.ts +1 -1
  185. package/dist/token-throttle/index.d.ts.map +1 -1
  186. package/dist/type-gate/index.d.ts +1 -1
  187. package/dist/type-gate/index.d.ts.map +1 -1
  188. package/dist/type-gate.js +11 -4
  189. package/package.json +80 -68
package/README.md CHANGED
@@ -1,7 +1,7 @@
1
1
  # @wrongstack/plugins
2
2
 
3
3
  First-party plugin collection for [WrongStack](https://github.com/WrongStack/WrongStack).
4
- Sixty-three focused, single-purpose plugins ship in this package. Passive,
4
+ Sixty-four focused, single-purpose plugins ship in this package. Passive,
5
5
  broadly applicable diagnostics and bounded safety checks load automatically;
6
6
  plugins with automatic mutation, policy enforcement, network egress, background
7
7
  work, or provider-call semantic changes are opt-in.
@@ -15,79 +15,15 @@ exports a default `Plugin` object. The host's plugin loader
15
15
  `ToolRegistry` and may also register **hooks** (e.g.
16
16
  `secret-scanner` registers `PreToolUse` + `PostToolUse` hooks).
17
17
 
18
- Plugins are loaded lazily by `packages/cli/src/wiring/plugins.ts`
19
- under the `BUILTIN_PLUGIN_FACTORIES` array. The canonical default is
20
- `PLUGIN_AUDIT_ENTRIES.defaultState`: list an inactive plugin with
18
+ Official plugins are loaded lazily through factories generated from the typed
19
+ manifest. The canonical default is each manifest entry's `audit.defaultState`:
20
+ list an inactive plugin with
21
21
  `{ name: '<plugin>', enabled: true }` to opt in, or list an active plugin with
22
22
  `enabled: false` to opt out.
23
23
 
24
24
  ## Plugin catalog
25
25
 
26
- | # | Plugin | Tools | Hooks | Notes |
27
- |---|---|---|---|---|
28
- | 1 | [`auto-doc`](./src/auto-doc) | `auto_doc` | — | JSDoc/TSDoc generation with `dry_run` preview |
29
- | 2 | [`git-autocommit`](./src/git-autocommit) | `git_autocommit` | — | AI-written conventional commits; warns on simultaneous worktrees |
30
- | 3 | [`shell-check`](./src/shell-check) | `shellcheck` | — | Runs `shellcheck` on files or directories |
31
- | 4 | [`cost-tracker`](./src/cost-tracker) | `cost_summary`, `cost_reset`, `cost_export` | — | Tracks per-model token usage and estimated USD cost |
32
- | 5 | [`file-watcher`](./src/file-watcher) | `watch_start`, `watch_stop`, `watch_list` | — | Watches project files and emits debounced change events |
33
- | 6 | [`cron`](./src/cron) | `cron_schedule`, `cron_list`, `cron_cancel` | — | Schedules recurring in-session actions |
34
- | 7 | [`template-engine`](./src/template-engine) | `template_expand`, `template_render`, `template_create`, `template_list` | — | Expands templates with variables, conditionals, and loops |
35
- | 8 | [`semver-bump`](./src/semver-bump) | `semver_bump`, `semver_current`, `semver_changelog` | — | Infers version bumps and changelogs from conventional commits |
36
- | 9 | [`secret-scanner`](./src/secret-scanner) | `secret_scanner_status`, `secret_scanner_test` | `PreToolUse` + `PostToolUse` | Blocks/redacts input secrets and warns on output leaks |
37
- | 10 | [`todo-tracker`](./src/todo-tracker) | `todo_tracker_*` | — | Persistent project-scoped backlog that survives sessions |
38
- | 11 | [`token-budget`](./src/token-budget) | `token_budget_status` | `Stop` + `PostToolUse` | Tracks token use and can warn/stop at configured limits |
39
- | 12 | [`lint-gate`](./src/lint-gate) | `lint_gate_status` | `PreToolUse` | Lints would-be write/edit content before mutation |
40
- | 13 | [`branch-guard`](./src/branch-guard) | `branch_guard_status` | `PreToolUse` | Opt-in protected-branch policy for commits, pushes, and merges |
41
- | 14 | [`diff-summary`](./src/diff-summary) | `diff_summary_status` | `PostToolUse` | Injects compact git diff context after write/edit |
42
- | 15 | [`commit-validator`](./src/commit-validator) | `commit_validator_status` | `PreToolUse` | Opt-in conventional-commit policy |
43
- | 16 | [`format-on-save`](./src/format-on-save) | `format_on_save_status` | `PostToolUse` | Runs formatter after write/edit |
44
- | 17 | [`test-runner-gate`](./src/test-runner-gate) | `test_gate_status` | `PostToolUse` | Runs relevant tests after source edits |
45
- | 18 | [`import-organizer`](./src/import-organizer) | `import_organizer_status` | `PostToolUse` | Organizes imports and applies safe fixes after write/edit |
46
- | 19 | [`todo-listener`](./src/todo-listener) | `todo_listener_status` | `PostToolUse` | Broadcasts todo status changes to the project mailbox |
47
- | 20 | [`session-recap`](./src/session-recap) | `session_recap_status` | `Stop` | Posts a compact session recap to the project mailbox |
48
- | 21 | [`spec-linker`](./src/spec-linker) | `spec_linker_status` | `PreToolUse` + `PostToolUse` | Detects unlinked plugin references in markdown docs |
49
- | 22 | [`loop-breaker`](./src/loop-breaker) | `loop_breaker_status` | `PreToolUse` | Detects repeated tool-call loops and oscillations |
50
- | 23 | [`path-guard`](./src/path-guard) | `path_guard_status` | `PreToolUse` | Opt-in protected-path policy for writes and destructive commands |
51
- | 24 | [`context-pins`](./src/context-pins) | `pin_add`, `pin_remove`, `pin_list` | System prompt contributor | Persists short pinned facts across compaction/session boundaries |
52
- | 25 | [`checkpoint`](./src/checkpoint) | `checkpoint_create`, `checkpoint_list`, `checkpoint_restore` | `PreToolUse` | Opt-in in-memory snapshots of pre-edit file contents |
53
- | 26 | [`error-lens`](./src/error-lens) | `error_lens_history` | `PostToolUse` | Summarizes failed tool output and repeated failure patterns |
54
- | 27 | [`dep-guard`](./src/dep-guard) | `dep_guard_status` | `PreToolUse` | Supervises dependency installs for deny-list and supply-chain warnings |
55
- | 28 | [`config-validator`](./src/config-validator) | `config_validator_status` | `PostToolUse` | Validates edited JSON/JSONC/YAML/TOML config files |
56
- | 29 | [`notify-hub`](./src/notify-hub) | `notify_send`, `notify_hub_status` | `Stop` + event subscriptions | Sends session/tool notifications to a configured webhook |
57
- | 30 | [`changelog-writer`](./src/changelog-writer) | `changelog_add`, `changelog_preview`, `changelog_write` | — | Collects and writes Keep-a-Changelog entries |
58
- | 31 | [`injection-shield`](./src/injection-shield) | `injection_shield_status` | `PostToolUse` | Warns when tool output contains prompt-injection patterns |
59
- | 32 | [`llm-cache`](./src/llm-cache) | `llm_cache_status`, `llm_cache_clear` | Provider runner wrapper | Opt-in cache for deterministic provider requests |
60
- | 33 | [`model-router`](./src/model-router) | `model_router_status` | Provider runner wrapper | Opt-in routing of provider calls by declarative rules |
61
- | 34 | [`prompt-firewall`](./src/prompt-firewall) | `prompt_firewall_status` | Provider runner wrapper | Opt-in provider-wire prompt/secret scanning and redaction/blocking |
62
- | 35 | [`auto-escalate`](./src/auto-escalate) | `auto_escalate_status` | `onError` extension | Opt-in retry/escalation ladder for transient provider errors |
63
- | 36 | [`token-throttle`](./src/token-throttle) | `token_throttle_status` | Provider runner wrapper | Opt-in rolling-window token throttling for provider calls |
64
- | 37 | [`type-gate`](./src/type-gate) | `type_gate_status` | `PostToolUse` | Runs `tsc --noEmit` after `write`/`edit` to catch type regressions |
65
- | 38 | [`test-coverage-gate`](./src/test-coverage-gate) | `coverage_gate_status` | `PostToolUse` | Detects test-coverage regressions after source-file edits |
66
- | 39 | [`pr-drafter`](./src/pr-drafter) | `pr_draft` | `Stop` + event subscriptions | Drafts a pull-request description from session commits/files/diff |
67
- | 40 | [`agent-handoff`](./src/agent-handoff) | `handoff_note`, `handoff_status` | `subagent.done` event listener | Opt-in mailbox publication of subagent results |
68
- | 41 | [`knowledge-graph`](./src/knowledge-graph) | `kg_add_fact`, `kg_query`, `kg_remove_fact`, `kg_status` | System prompt contributor | Persistent structured (subject, relation, object) project facts |
69
- | 42 | [`dead-code-detector`](./src/dead-code-detector) | `dead_code_scan` | `PostToolUse` | Regex-based scan for exported identifiers that appear unused |
70
- | 43 | [`dependency-vulnerability-gate`](./src/dependency-vulnerability-gate) | `dependency_audit_status` | `PostToolUse` | Opt-in blocking `npm/pnpm audit` after installs |
71
- | 44 | [`migration-planner`](./src/migration-planner) | `migration_plan`, `migration_status` | `PostToolUse` | Evidence-backed checklists + optional `api.llm` risk/verification analysis |
72
- | 45 | [`semantic-search-indexer`](./src/semantic-search-indexer) | `semantic_search`, `semantic_index_status` | — | Lightweight keyword index over project source files |
73
- | 46 | [`auto-i18n-extractor`](./src/auto-i18n-extractor) | `i18n_extract`, `i18n_status` | `PostToolUse` | Detects hardcoded user-facing strings and suggests i18n keys |
74
- | 47 | [`doc-sync-guard`](./src/doc-sync-guard) | `doc_sync_status` | `PostToolUse` | Warns when README/docs edits omit recently changed source files |
75
- | 48 | [`api-compatibility-gate`](./src/api-compatibility-gate) | `api_compat_status` | `PostToolUse` | Detects removed exports in entry-point files as breaking changes |
76
- | 49 | [`performance-regression-gate`](./src/performance-regression-gate) | `perf_regression_status` | — | Compares benchmark results and reports regressions |
77
- | 50 | [`test-flake-detector`](./src/test-flake-detector) | `flake_detect`, `flake_status` | — | Runs a test command N times to identify flaky tests |
78
- | 51 | [`schema-evolution-guard`](./src/schema-evolution-guard) | `schema_evolution_status` | `PostToolUse` | Detects destructive patterns in DB/API schema files |
79
- | 52 | [`license-audit-gate`](./src/license-audit-gate) | `license_audit_status` | `PostToolUse` | Audits newly added dependency licenses against an allowlist |
80
- | 53 | [`accessibility-auditor`](./src/accessibility-auditor) | `a11y_audit`, `a11y_status` | `PostToolUse` | Audits UI files for missing alt, labels, button text, duplicate ids |
81
- | 54 | [`security-hotspot-scanner`](./src/security-hotspot-scanner) | `security_hotspot_scan`, `security_hotspot_status` | `PostToolUse` | Scans source for security anti-patterns after writes/edits |
82
- | 55 | [`duplicate-code-detector`](./src/duplicate-code-detector) | `detect_duplicate_code`, `duplicate_code_status` | `PostToolUse` | Detects duplicate/similar code blocks using normalized-line fingerprints |
83
- | 56 | [`code-metrics`](./src/code-metrics) | `measure_code_metrics`, `metrics_status` | `PostToolUse` | Computes LOC, comment ratio, function count, and approximate cyclomatic complexity |
84
- | 57 | [`refactor-suggester`](./src/refactor-suggester) | `suggest_refactors`, `refactor_status` | `PostToolUse` | Flags long functions, deep nesting, many parameters, magic numbers, console.log |
85
- | 58 | [`test-generator`](./src/test-generator) | `generate_unit_tests` | — | Framework-correct skeletons + optional behavior-focused `api.llm` tests |
86
- | 59 | [`release-notes-generator`](./src/release-notes-generator) | `generate_release_notes` | — | Traceable notes + optional hash-preserving `api.llm` polish |
87
- | 60 | [`smart-rename`](./src/smart-rename) | `smart_rename` | — | Whole-word symbol rename with preview and optional apply |
88
- | 61 | [`feature-flag-tracker`](./src/feature-flag-tracker) | `scan_feature_flags`, `feature_flag_status` | `PostToolUse` | Scans source files for feature-flag usage and reports flag inventory |
89
- | 62 | [`interface-contract-guard`](./src/interface-contract-guard) | `check_interface_contracts`, `interface_contract_status` | `PostToolUse` | Warns when TypeScript interfaces change or lack implementers |
90
- | 63 | [`plugin-stack-observer`](./src/plugin-stack-observer) | `plugin_stack_status` | Event listener + optional system prompt contributor | Reports active provider-runner wrappers in registration order |
26
+ Plugin identity, import paths, versions, API ranges, and descriptions are generated from the typed manifest in [`PLUGIN_CATALOG.md`](./PLUGIN_CATALOG.md). Run `pnpm plugins:manifest:write` after changing the manifest.
91
27
 
92
28
  ### Removed plugins (use built-in tools instead)
93
29
 
@@ -702,7 +638,7 @@ context. Increase `includeTranscriptTail` for more history.
702
638
  Two hooks working together:
703
639
 
704
640
  **PostToolUse** (always active when the plugin is enabled):
705
- scans markdown files for *unlinked* references to one of the 63
641
+ scans markdown files for *unlinked* references to one of the manifest-listed
706
642
  known plugins and surfaces them to the LLM via
707
643
  `additionalContext`. The plugin does NOT modify the file — it
708
644
  only injects a low-noise context block listing the unlinked
@@ -726,7 +662,7 @@ the PostToolUse context tells the LLM what to fix.
726
662
 
727
663
  **Detection rules** (both hooks):
728
664
  - Source matches `config.fileGlobs` (default: `**/*.md`, `**/*.mdx`)
729
- - The reference matches one of the 63 known plugin names
665
+ - The reference matches one of the manifest-listed plugin names
730
666
  (case-insensitive)
731
667
  - It is NOT already wrapped in a markdown link `[name](...)` or
732
668
  inline code `` `name` ``
@@ -24,7 +24,7 @@
24
24
  *
25
25
  * @public
26
26
  */
27
- import type { Plugin } from '@wrongstack/core';
27
+ import type { Plugin } from '@wrongstack/core/types';
28
28
  export type A11yRule = 'missing-alt' | 'missing-input-label' | 'low-contrast-placeholder' | 'missing-button-text' | 'duplicate-id';
29
29
  export interface A11yFinding {
30
30
  file: string;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/accessibility-auditor/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAIH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAS/C,MAAM,MAAM,QAAQ,GAChB,aAAa,GACb,qBAAqB,GACrB,0BAA0B,GAC1B,qBAAqB,GACrB,cAAc,CAAC;AAEnB,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,QAAQ,CAAC;IACf,QAAQ,EAAE,OAAO,GAAG,SAAS,CAAC;IAC9B,OAAO,EAAE,MAAM,CAAC;CACjB;AAoPD,QAAA,MAAM,MAAM,EAAE,MA0Nb,CAAC;eAEa,MAAM"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/accessibility-auditor/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAIH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AASrD,MAAM,MAAM,QAAQ,GAChB,aAAa,GACb,qBAAqB,GACrB,0BAA0B,GAC1B,qBAAqB,GACrB,cAAc,CAAC;AAEnB,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,QAAQ,CAAC;IACf,QAAQ,EAAE,OAAO,GAAG,SAAS,CAAC;IAC9B,OAAO,EAAE,MAAM,CAAC;CACjB;AAuPD,QAAA,MAAM,MAAM,EAAE,MA0Nb,CAAC;eAEa,MAAM"}
@@ -1,9 +1,8 @@
1
1
  // src/accessibility-auditor/index.ts
2
- import { readFileSync } from "node:fs";
2
+ import { readFile } from "node:fs/promises";
3
3
  import { isAbsolute as isAbsolute2, relative as relative2, resolve as resolve2 } from "node:path";
4
4
 
5
5
  // src/runtime/index.ts
6
- import { existsSync, readdirSync, statSync } from "node:fs";
7
6
  import { basename, extname, isAbsolute, relative, resolve } from "node:path";
8
7
  var MAX_BUFFER_BYTES = 16 * 1024 * 1024;
9
8
  function hasLeadingDash(arg) {
@@ -17,44 +16,45 @@ function withinProjectPath(projectRoot, candidate) {
17
16
  return rel === "" || !rel.startsWith("..") && !isAbsolute(rel);
18
17
  }
19
18
  function withinProject(p) {
20
- return withinProjectPath(process.cwd(), p) || relative(process.cwd(), p) === ".";
19
+ const cwd = process.cwd();
20
+ return withinProjectPath(cwd, p) || relative(cwd, p) === ".";
21
21
  }
22
22
  var DEFAULT_EXCLUDE_DIRS = ["node_modules", "dist", ".git", "coverage"];
23
- function collectSourceFiles(root, opts) {
23
+ async function collectSourceFilesAsync(root, opts) {
24
+ const { readdir, stat } = await import("node:fs/promises");
24
25
  const files = [];
25
- if (!existsSync(root)) return files;
26
- const s = statSync(root);
27
- if (s.isFile()) {
28
- if (matchesExtension(root, opts.extensions)) files.push(root);
26
+ try {
27
+ const s = await stat(root);
28
+ if (s.isFile()) {
29
+ if (matchesExtension(root, opts.extensions)) files.push(root);
30
+ return files;
31
+ }
32
+ if (!s.isDirectory()) return files;
33
+ } catch {
29
34
  return files;
30
35
  }
31
- if (!s.isDirectory()) return files;
32
36
  const exclude = opts.excludeDirs ?? DEFAULT_EXCLUDE_DIRS;
33
- function walk(dir, depth) {
37
+ const excludeSet = new Set(exclude);
38
+ async function walk(dir, depth) {
34
39
  if (opts.maxDepth !== void 0 && depth > opts.maxDepth) return;
35
40
  let entries;
36
41
  try {
37
- entries = readdirSync(dir);
42
+ entries = await readdir(dir, { withFileTypes: true });
38
43
  } catch {
39
44
  return;
40
45
  }
46
+ entries.sort((a, b) => a.name.localeCompare(b.name));
41
47
  for (const entry of entries) {
42
- if (exclude.includes(entry)) continue;
43
- const full = resolve(dir, entry);
44
- let st;
45
- try {
46
- st = statSync(full);
47
- } catch {
48
- continue;
49
- }
50
- if (st.isDirectory()) {
51
- walk(full, depth + 1);
52
- } else if (st.isFile() && matchesExtension(full, opts.extensions)) {
48
+ if (excludeSet.has(entry.name)) continue;
49
+ const full = resolve(dir, entry.name);
50
+ if (entry.isDirectory()) {
51
+ await walk(full, depth + 1);
52
+ } else if (entry.isFile() && matchesExtension(full, opts.extensions)) {
53
53
  files.push(full);
54
54
  }
55
55
  }
56
56
  }
57
- walk(root, 0);
57
+ await walk(root, 0);
58
58
  return files;
59
59
  }
60
60
  function matchesExtension(p, exts) {
@@ -109,10 +109,10 @@ function hasMeaningfulAlt(tag) {
109
109
  const valMatch = tag.match(/\balt\s*=\s*["']?([^"'\s>]*)["']?/i);
110
110
  return valMatch ? valMatch[1].trim().length > 0 : false;
111
111
  }
112
- function auditFile(filePath, projectRoot) {
112
+ async function auditFile(filePath, projectRoot) {
113
113
  let content;
114
114
  try {
115
- content = readFileSync(filePath, "utf-8");
115
+ content = await readFile(filePath, "utf-8");
116
116
  } catch {
117
117
  return [];
118
118
  }
@@ -198,14 +198,14 @@ function auditFile(filePath, projectRoot) {
198
198
  }
199
199
  return findings;
200
200
  }
201
- function auditPath(rawPath, cfg) {
201
+ async function auditPath(rawPath, cfg) {
202
202
  const root = process.cwd();
203
203
  const resolved = isAbsolute2(rawPath) ? resolve2(rawPath) : resolve2(root, rawPath);
204
204
  const exts = normalizeExtensions(cfg.includeExtensions);
205
- const files = collectSourceFiles(resolved, { extensions: exts });
205
+ const files = await collectSourceFilesAsync(resolved, { extensions: exts });
206
206
  const findings = [];
207
207
  for (const file of files) {
208
- const fileFindings = auditFile(file, root);
208
+ const fileFindings = await auditFile(file, root);
209
209
  findings.push(...fileFindings);
210
210
  if (findings.length >= cfg.maxFindings) break;
211
211
  }
@@ -274,7 +274,7 @@ var plugin = {
274
274
  state.lastResult = null;
275
275
  state.hookUnregister = null;
276
276
  const cfg = readConfig(api.config.extensions?.["accessibility-auditor"]);
277
- const hook = (input) => {
277
+ const hook = async (input) => {
278
278
  if (!cfg.enabled || !cfg.onWriteEdit) return;
279
279
  if (input.toolResult?.isError) return;
280
280
  const inp = input.toolInput ?? {};
@@ -284,7 +284,7 @@ var plugin = {
284
284
  const exts = normalizeExtensions(cfg.includeExtensions);
285
285
  if (!matchesExtension(sourcePath, exts)) return;
286
286
  state.hookInvocationCount += 1;
287
- const result = auditPath(sourcePath, cfg);
287
+ const result = await auditPath(sourcePath, cfg);
288
288
  state.auditCount += 1;
289
289
  state.fileCount += result.fileCount;
290
290
  state.findingCount += result.findings.length;
@@ -328,7 +328,7 @@ var plugin = {
328
328
  return { ok: false, error: "path must be inside the project" };
329
329
  }
330
330
  state.auditCount += 1;
331
- const result = auditPath(rawPath, cfg);
331
+ const result = await auditPath(rawPath, cfg);
332
332
  state.fileCount += result.fileCount;
333
333
  state.findingCount += result.findings.length;
334
334
  state.lastResult = {
@@ -29,7 +29,7 @@
29
29
  *
30
30
  * @public
31
31
  */
32
- import type { Plugin } from '@wrongstack/core';
32
+ import type { Plugin } from '@wrongstack/core/types';
33
33
  declare const plugin: Plugin;
34
34
  export default plugin;
35
35
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/agent-handoff/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAEH,OAAO,KAAK,EAAE,MAAM,EAA6B,MAAM,kBAAkB,CAAC;AAwK1E,QAAA,MAAM,MAAM,EAAE,MAsNb,CAAC;eAEa,MAAM"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/agent-handoff/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAGH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAwKrD,QAAA,MAAM,MAAM,EAAE,MAsNb,CAAC;eAEa,MAAM"}
@@ -30,7 +30,7 @@
30
30
  *
31
31
  * @public
32
32
  */
33
- import type { Plugin } from '@wrongstack/core';
33
+ import type { Plugin } from '@wrongstack/core/types';
34
34
  declare const plugin: Plugin;
35
35
  export default plugin;
36
36
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/api-compatibility-gate/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAKH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAkR/C,QAAA,MAAM,MAAM,EAAE,MA6Mb,CAAC;eAEa,MAAM"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/api-compatibility-gate/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAMH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAsRrD,QAAA,MAAM,MAAM,EAAE,MA6Mb,CAAC;eAEa,MAAM"}
@@ -1,6 +1,7 @@
1
1
  // src/api-compatibility-gate/index.ts
2
- import { execFileSync } from "node:child_process";
2
+ import { execFile } from "node:child_process";
3
3
  import { existsSync, readFileSync } from "node:fs";
4
+ import { readFile } from "node:fs/promises";
4
5
  import { basename, dirname, extname, isAbsolute, relative, resolve } from "node:path";
5
6
  var API_VERSION = "^0.1.10";
6
7
  var state = {
@@ -155,21 +156,25 @@ function extractExports(source) {
155
156
  function readGitVersion(filePath) {
156
157
  const resolved = resolveToProjectRoot(filePath);
157
158
  const relPath = normalizePath(relative(process.cwd(), resolved));
158
- try {
159
- const out = execFileSync("git", ["show", `HEAD:${relPath}`], {
160
- encoding: "utf-8",
161
- cwd: process.cwd(),
162
- stdio: ["pipe", "pipe", "pipe"]
163
- });
164
- return out;
165
- } catch {
166
- return null;
167
- }
159
+ return new Promise((resolveVersion) => {
160
+ execFile(
161
+ "git",
162
+ ["show", `HEAD:${relPath}`],
163
+ {
164
+ encoding: "utf8",
165
+ cwd: process.cwd(),
166
+ windowsHide: true,
167
+ timeout: 5e3,
168
+ maxBuffer: 5 * 1024 * 1024
169
+ },
170
+ (error, stdout) => resolveVersion(error ? null : stdout)
171
+ );
172
+ });
168
173
  }
169
- function readCurrentFile(filePath) {
174
+ async function readCurrentFile(filePath) {
170
175
  try {
171
176
  const resolved = resolveToProjectRoot(filePath);
172
- return readFileSync(resolved, "utf-8");
177
+ return await readFile(resolved, "utf8");
173
178
  } catch {
174
179
  return null;
175
180
  }
@@ -227,7 +232,7 @@ var plugin = {
227
232
  state.hookUnregister = null;
228
233
  }
229
234
  const cfg = readConfig(api.config.extensions?.["api-compatibility-gate"]);
230
- const hook = (input) => {
235
+ const hook = async (input) => {
231
236
  if (!cfg.enabled) return;
232
237
  if (input.toolResult?.isError) return;
233
238
  const inp = input.toolInput ?? {};
@@ -242,12 +247,12 @@ var plugin = {
242
247
  state.skippedCount += 1;
243
248
  return;
244
249
  }
245
- const before = readGitVersion(filePath);
250
+ const before = await readGitVersion(filePath);
246
251
  if (before === null) {
247
252
  state.skippedCount += 1;
248
253
  return;
249
254
  }
250
- const after = readCurrentFile(filePath);
255
+ const after = await readCurrentFile(filePath);
251
256
  if (after === null) {
252
257
  state.errorCount += 1;
253
258
  return;