@wrongstack/core 0.141.0 → 0.148.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wrongstack/core",
3
- "version": "0.141.0",
3
+ "version": "0.148.0",
4
4
  "license": "MIT",
5
5
  "description": "WrongStack core: kernel, types, defaults, and shared utilities for the WrongStack CLI agent.",
6
6
  "repository": {
@@ -2,159 +2,315 @@
2
2
  name: tech-stack
3
3
  description: |
4
4
  Use this skill when choosing, installing, or recommending packages, libraries,
5
- frameworks, or tooling any decision that involves a version number or a
6
- technology name. This skill enforces latest-version verification, blocks
7
- dead/obsolete choices, and intervenes when the LLM hallucinates version
8
- numbers or suggests 5+ year-old technology.
5
+ frameworks, or tooling for ANY programming language decisions that involve
6
+ a version number or a technology name. This skill detects the ecosystem,
7
+ verifies latest versions against the correct registry, blocks dead/obsolete
8
+ choices, and intervenes when the LLM hallucinates version numbers or
9
+ suggests 5+ year-old technology.
9
10
  Triggers: user says "install", "package", "dependency", "upgrade",
10
- "latest version", "add package", "npm install", "pnpm add", "what version",
11
+ "latest version", "add package", "pip install", "cargo add", "go get",
12
+ "gem install", "composer require", "nuget", "what version",
11
13
  "which library", "tech stack", "choose framework".
12
- version: 1.0.0
14
+ version: 2.0.0
13
15
  ---
14
16
 
15
- # Tech Stack Validator — WrongStack
17
+ # Tech Stack Validator — WrongStack (Language-Agnostic)
16
18
 
17
19
  ## Overview
18
20
 
19
21
  Intervening validation layer that fires before a package, library, or framework
20
- choice is committed. Verifies that the selected technology and version are
21
- current, exist in reality, and are not dead/abandoned. Runs as a single-shot
22
- delegate fast, read-only, fire-and-forget.
22
+ choice is committed for **any language**. Uses an ecosystem adapter pattern:
23
+ core validation logic is universal; the registry endpoint, package manager
24
+ command, prehistoric reject list, and built-in preference map vary per
25
+ ecosystem. Runs as a single-shot delegate — fast, read-only, fire-and-forget.
23
26
 
24
27
  ## Rules
25
28
 
26
- 1. **Verify existence.** Before accepting a package name, search the npm registry
27
- (`https://registry.npmjs.org/<package>/latest`) or the equivalent package
28
- index. A package that doesn't exist in the registry is a hallucination.
29
-
30
- 2. **Check latest version.** Always fetch the actual latest stable version.
31
- The LLM's training data is stale — never trust a version number from the
32
- model without checking.
33
-
34
- 3. **Reject dead packages.** If a package has had no release in >2 years AND
29
+ 1. **Detect the ecosystem first.** Before anything else, determine which
30
+ language/ecosystem the package belongs to. Two strategies, tried in order:
31
+ - **Explicit**: The user names the language ("add `requests` to our Python project")
32
+ - **Implied**: Scan project files for ecosystem markers:
33
+ - `package.json` (js), `tsconfig.json` (ts) **JavaScript/TypeScript**
34
+ - `pyproject.toml`, `setup.py`, `setup.cfg`, `requirements.txt` **Python**
35
+ - `Cargo.toml` → **Rust**
36
+ - `go.mod` → **Go**
37
+ - `Gemfile` **Ruby**
38
+ - `*.csproj`, `*.fsproj`, `packages.config` → **.NET**
39
+ - `composer.json` → **PHP**
40
+ - `mix.exs` → **Elixir**
41
+ - `pom.xml`, `build.gradle` → **Java/JVM**
42
+ - If multiple markers exist, ask the user which ecosystem.
43
+ - If NO markers exist and the user hasn't specified, default to **JavaScript**
44
+ when `package.json` is present, otherwise ask.
45
+
46
+ 2. **Verify existence.** Consult the registry for the detected ecosystem
47
+ (see Ecosystem Registry Map below). Fetch the package endpoint. A package
48
+ that returns 404 or doesn't exist in the registry is a hallucination.
49
+
50
+ 3. **Check latest version.** Always fetch the actual latest stable version from
51
+ the ecosystem's registry. The LLM's training data is stale — never trust a
52
+ version number from the model without checking.
53
+
54
+ 4. **Reject dead packages.** If a package has had no release in >2 years AND
35
55
  has unresolved critical issues, flag it as dead. Suggest a maintained
36
- replacement.
37
-
38
- 4. **Reject prehistoric technology.** Any package/library/pattern that was
39
- superseded ≥5 years ago is automatically rejected. Examples that MUST be
40
- blocked:
41
- - `axios`, `node-fetch`, `got` → native `fetch` (Node 18+, 2022)
42
- - `request` (deprecated 2020) → native `fetch`
43
- - `moment` `date-fns`, `luxon`, or `Temporal`
44
- - `left-pad` native `String.prototype.padStart`
45
- - `crypto-js` native `Web Crypto` / `node:crypto`
46
- - `jQuery` for new projects vanilla DOM / React
47
- - `Backbone`, `Ember` → React / Vue / Svelte
48
- - `Gulp`, `Grunt` `tsup`, `esbuild`, `vite`
49
- - `Bower` npm/pnpm
50
- - `CoffeeScript` TypeScript
51
- - `Flow` → TypeScript
52
- - `Bluebird` → native Promises
53
- - `underscore` → `lodash` or native ES2020+
54
- - `classnames` → `clsx` or native `classList`
55
-
56
- 5. **Intervene with evidence.** When blocking a choice, output the exact phrase
57
- **"This isn't code, this is X-year-old technology"** with:
58
- - The actual age (X = current year − release year)
59
- - What superseded it
60
- - A concrete migration path (one package, one import change)
61
-
62
- 6. **Prefer built-in over third-party.** Every Node.js LTS release adds native
63
- APIs that obsolete packages. Check Node 22+ built-ins before suggesting an
64
- npm package:
65
- - `node:test` over `jest`/`mocha` (for new projects)
66
- - `node:sqlite` over `better-sqlite3` (Node 22.5+)
67
- - `fetch`, `WebSocket`, `Web Crypto`, `AbortController`, `EventTarget` —
68
- all native, no packages needed
56
+ replacement. Registry-specific dead signals:
57
+ - npm: `"deprecated"` field, archived GitHub repo
58
+ - PyPI: yanked releases, `Development Status :: 7 - Inactive` classifier
59
+ - Crates.io: yanked versions, archived repo
60
+ - Rubygems: `"version": null` for yanked, archived repo
61
+ - NuGet: deprecated flag, `listed: false`
62
+
63
+ 5. **Reject prehistoric technology.** Any package/library/pattern that was
64
+ superseded ≥5 years ago is automatically rejected. Use the per-ecosystem
65
+ reject lists below. If the package is NOT in the baked-in list, fall back
66
+ to web search: `"is <package> deprecated <ecosystem> <current_year>"`.
67
+
68
+ 6. **Prefer built-in over third-party.** Every modern language runtime ships
69
+ standard library that obsoletes packages. Check the per-ecosystem built-in
70
+ map below before greenlighting any third-party dependency.
69
71
 
70
72
  7. **Single-shot budget.** This agent is not for deep analysis — it should
71
- complete in 1–2 iterations. Search → verify → report. Do not recursively
72
- analyze transitive dependencies.
73
+ complete in 1–2 iterations. Detectsearch registry → verify → report.
74
+ Do not recursively analyze transitive dependencies.
73
75
 
74
76
  ## Patterns
75
77
 
76
78
  ### Do
77
79
 
78
80
  ```
79
- User: "Add axios for API calls"
80
- Agent: REJECTED
81
- "This isn't code, this is 10-year-old technology."
82
- axios was released in 2014. Node.js 18+ (2022) includes native fetch with
83
- AbortSignal.timeout(), streaming, and FormData. No package needed.
84
- → Use: `const res = await fetch(url, { signal: AbortSignal.timeout(5000) })`
81
+ User: "Add requests to the project"
82
+ Agent: [detects pyproject.toml → Python ecosystem]
83
+ requests 2.32.4 (latest stable as of 2026-06)
84
+ Verified via PyPI. requests is the de-facto HTTP library for Python.
85
+ **Install**: `pip install requests>=2.32`
86
+ ```
87
+
88
+ ```
89
+ User: "Cargo add serde"
90
+ Agent: [detects Cargo.toml → Rust ecosystem]
91
+ ✅ serde 1.0.217 (latest stable)
92
+ Verified via crates.io. serde is the standard serialization framework for Rust.
93
+ **Install**: `cargo add serde@1`
85
94
  ```
86
95
 
87
96
  ```
88
- User: "What version of React should we use?"
89
- Agent: React 19.2.1 (latest stable as of 2026-06-08)
90
- Verified via npm registry. React 19 includes Server Components,
91
- use() hook, and ref-as-prop. Pin to ^19.2.0 for semver safety.
97
+ User: "Add urllib2 for HTTP calls in our Python project"
98
+ Agent: REJECTED
99
+ "This isn't code, this is 16-year-old technology."
100
+ urllib2 was part of Python 2.x (released 2000). Python 3 unified everything
101
+ into `urllib.request` (stdlib) and `requests` (third-party, the community
102
+ standard). No package needed — or use `requests` for a better API.
103
+ → Use: `import requests` or `from urllib.request import urlopen`
92
104
  ```
93
105
 
94
106
  ```
95
- User: "Install typescript"
96
- Agent: TypeScript 5.9.3 (latest stable)
97
- Verified via npm registry. Use `^5.9.0` to receive patch updates.
107
+ User: "Add axios for API calls"
108
+ Agent: REJECTED
109
+ "This isn't code, this is 12-year-old technology."
110
+ axios was released in 2014. Node.js 18+ (2022) includes native fetch with
111
+ AbortSignal.timeout(), streaming, and FormData. No package needed.
112
+ → Use: `const res = await fetch(url, { signal: AbortSignal.timeout(5000) })`
98
113
  ```
99
114
 
100
115
  ### Don't
101
116
 
102
117
  ```
103
- // ❌ Trusting the LLM's stale training data
118
+ ❌ Trusting the LLM's stale training data
104
119
  Agent: "Use React 18.3.1 — it's the latest stable."
105
- // WRONG React 19 has been stable since Dec 2024. Check npm.
120
+ WRONG. React 19 has been stable since Dec 2024. Always check the registry.
106
121
 
107
- // Suggesting axios without challenge
108
- Agent: "npm install axios" — no justification, no fetch alternative mentioned.
122
+ Assuming npm for everything
123
+ Agent: "pnpm add django" — Django is a Python package. Ecosystem detection
124
+ must happen before any install command is suggested.
109
125
 
110
- // ❌ Accepting a package that doesn't exist
111
- Agent: "Install @anthropic/sdk version 2.0.0" — verify this version exists first.
126
+ ❌ Accepting a package that doesn't exist
127
+ Agent: "Install @anthropic/sdk version 2.0.0" — verify against the correct registry first.
112
128
 
113
- // ❌ Suggesting moment.js
129
+ ❌ Suggesting moment.js without challenge
114
130
  Agent: "Use moment for date formatting" — moment is legacy. Suggest date-fns or Temporal.
115
131
  ```
116
132
 
117
133
  ## Workflow
118
134
 
119
135
  ```
120
- 1. Receive Package name + proposed version (or "latest")
121
- 2. Search npm registry: https://registry.npmjs.org/<pkg>/latest
122
- OR web search: "<package> latest version npm 2026"
123
- 3. Verify Does the package exist? Is the version real?
124
- 4. Audit — Age check. Last release date > 2 years? Dead?
125
- Prehistoric check. Was it superseded ≥5 years ago?
126
- 5. Report — APPROVED (with latest version) or REJECTED (with replacement)
136
+ 0. DETECT What ecosystem is this? (explicit hint → project files → ask)
137
+ 1. LOOKUP Find registry adapter for the ecosystem (see map below)
138
+ 2. VERIFY — Fetch {registry.host}{registry.path/{pkg}} extract {registry.field}
139
+ 3. AUDIT Age check (>2 years no release?), prehistoric check (in reject list?),
140
+ built-in check (stdlib alternative?), dead signals (deprecated/yanked?)
141
+ 4. REPORT — APPROVED (with latest version + install command)
142
+ or REJECTED (with replacement + migration step + evidence)
127
143
  Use the exact phrase "This isn't code, this is X-year-old technology"
128
- when rejecting on age grounds.
144
+ when rejecting on age/prehistoric grounds.
129
145
  ```
130
146
 
131
- ## Version checking — web sources
132
-
133
- When checking a package version, search in this order:
134
- 1. **npm registry**: `fetch('https://registry.npmjs.org/<package>/latest')` → `version` field
135
- 2. **npm API**: `fetch('https://api.npmjs.org/versions/<package>/last-week')`
136
- 3. **Web search**: `"<package> latest version 2026 npm"` on DuckDuckGo/Google
137
- 4. **GitHub releases**: `fetch('https://api.github.com/repos/<owner>/<repo>/releases/latest')`
138
-
139
- ## Dead package criteria
147
+ ## Ecosystem Registry Map
148
+
149
+ The central dispatch table. When verifying a package, use the adapter for the
150
+ detected ecosystem:
151
+
152
+ | ID | Language | Registry Host | Path Template | Version Field | Package Manager | Install Command |
153
+ |----|----------|--------------|---------------|---------------|-----------------|-----------------|
154
+ | `js` | JavaScript/TS | `registry.npmjs.org` | `/{pkg}/latest` | `version` | npm/pnpm/yarn | `pnpm add {pkg}@{version}` |
155
+ | `python` | Python | `pypi.org` | `/pypi/{pkg}/json` | `info.version` | pip/poetry/uv | `pip install {pkg}=={version}` |
156
+ | `rust` | Rust | `crates.io` | `/api/v1/crates/{pkg}` | `crate.max_stable_version` | cargo | `cargo add {pkg}@{major}` |
157
+ | `go` | Go | `proxy.golang.org` | `/{pkg}/@latest` | *(plain text)* | go | `go get {pkg}@{version}` |
158
+ | `ruby` | Ruby | `rubygems.org` | `/api/v1/gems/{pkg}.json` | `version` | bundler | `gem "{pkg}", "~> {major}.{minor}"` |
159
+ | `dotnet` | .NET | `api.nuget.org` | `/v3/registration5-gz-semver2/{pkg_lower}/index.json` | `items[0].upper` | dotnet | `dotnet add package {pkg} --version {version}` |
160
+ | `php` | PHP | `repo.packagist.org` | `/p2/{vendor}/{pkg}.json` | `packages[..].0.version` | composer | `composer require {vendor}/{pkg}:^{major}.{minor}` |
161
+ | `elixir` | Elixir | `hex.pm` | `/api/packages/{pkg}` | `releases[0].version` | mix | `{:pkg, "~> {major}.{minor}"}` (add to mix.exs) |
162
+ | `jvm` | Java/JVM | `search.maven.org` | `/solrsearch/select?q=g:{group}+AND+a:{artifact}&rows=1&wt=json` | `response.docs[0].latestVersion` | maven/gradle | `implementation '{group}:{artifact}:{version}'` |
163
+
164
+ **For registry endpoints that return complex nested structures** (NuGet, Packagist,
165
+ Maven), fetch the endpoint, parse the JSON, then navigate to the version field
166
+ as specified. If the API shape has changed, fall back to web search.
167
+
168
+ **For ecosystems NOT in this table**, detect the language, then web-search
169
+ `"<language> package registry API latest version"` to discover the endpoint.
170
+
171
+ ### Version checking — fallback chain
172
+
173
+ When the registry adapter is insufficient, try in this order:
174
+ 1. **Registry API** (primary): fetch per the Ecosystem Registry Map above
175
+ 2. **GitHub releases**: `fetch('https://api.github.com/repos/<owner>/<repo>/releases/latest')`
176
+ 3. **Web search**: `"<package> latest version <ecosystem> <current_year>"`
177
+ 4. **Project homepage**: fetch the package's documented "Install" page
178
+
179
+ ## Per-Ecosystem Reject Lists
180
+
181
+ ### JavaScript / TypeScript
182
+
183
+ | Prehistoric | Age | Replacement |
184
+ |-------------|-----|-------------|
185
+ | `axios`, `node-fetch`, `got`, `request` | 10-13yr | native `fetch` (Node 18+, 2022) |
186
+ | `moment` | 14yr | `date-fns`, `luxon`, or `Temporal` |
187
+ | `left-pad` | 10yr | native `String.prototype.padStart` |
188
+ | `crypto-js` | 12yr | native `Web Crypto` / `node:crypto` |
189
+ | `jQuery` (new projects) | 18yr | vanilla DOM / React / Vue / Svelte |
190
+ | `Backbone`, `Ember` | 14-15yr | React / Vue / Svelte |
191
+ | `Gulp`, `Grunt` | 12-13yr | `tsup`, `esbuild`, `vite` |
192
+ | `Bower` | 13yr | npm / pnpm |
193
+ | `CoffeeScript` | 16yr | TypeScript |
194
+ | `Flow` | 10yr | TypeScript |
195
+ | `Bluebird` | 12yr | native Promises |
196
+ | `underscore` | 16yr | `lodash` or native ES2020+ |
197
+ | `classnames` | 10yr | `clsx` or native `classList` |
198
+
199
+ ### Python
200
+
201
+ | Prehistoric | Age | Replacement |
202
+ |-------------|-----|-------------|
203
+ | `urllib2`, `httplib` | 20+yr | `requests` or `httpx` |
204
+ | `distutils`, `setup.py` (new projects) | 20+yr | `pyproject.toml` + `hatch`/`poetry`/`setuptools` |
205
+ | `os.path` for path manipulation | — | `pathlib` (stdlib since 3.4) |
206
+ | `mock` (third-party) | 12yr | `unittest.mock` (stdlib since 3.3) |
207
+ | `pathlib2` | 8yr | `pathlib` (stdlib since 3.4) |
208
+ | `python-dateutil` (basic usage) | — | `datetime` + `zoneinfo` (stdlib 3.9+) |
209
+ | `typing` (backport) | — | stdlib `typing` (3.5+) |
210
+ | `2to3` tooling | 16yr | Python 3 is the only supported version |
211
+ | `futures` (backport) | — | `concurrent.futures` (stdlib 3.2+) |
212
+
213
+ ### Rust
214
+
215
+ | Prehistoric | Age | Replacement |
216
+ |-------------|-----|-------------|
217
+ | `lazy_static` | 8yr | `std::sync::LazyLock` (1.80+, 2024) or `once_cell` |
218
+ | `try!` macro | 10yr | `?` operator (1.13+, 2016) |
219
+ | `error-chain` | 8yr | `thiserror` + `anyhow` |
220
+ | `rustc-serialize` | 10yr | `serde` |
221
+
222
+ ### Go
223
+
224
+ | Prehistoric | Age | Replacement |
225
+ |-------------|-----|-------------|
226
+ | `dep` (tool) | 8yr | Go modules (`go mod`, 1.11+, 2018) |
227
+ | `ioutil` (stdlib, deprecated) | — | `io` + `os` packages (1.16+, 2021) |
228
+ | `gopath` dependency management | 10+yr | Go modules |
229
+ | `gopkg.in/yaml.v2` (for new code) | — | `gopkg.in/yaml.v3` or `encoding/json` |
230
+ | `glide`, `godep` | 9-10yr | Go modules |
231
+
232
+ ### Ruby
233
+
234
+ | Prehistoric | Age | Replacement |
235
+ |-------------|-----|-------------|
236
+ | `therubyracer` | 12yr | `mini_racer` or Node.js-based execjs |
237
+ | `json` gem (explicit) | — | stdlib `json` (bundled since 2.3) |
238
+ | `rails` < 6.x (new projects) | 7+yr | Rails 7.x / 8.x |
239
+ | `protected_attributes` | 10yr | `strong_parameters` (Rails 4+) |
240
+
241
+ ### .NET
242
+
243
+ | Prehistoric | Age | Replacement |
244
+ |-------------|-----|-------------|
245
+ | `System.Web` / WebForms | 20+yr | ASP.NET Core |
246
+ | `Windows Forms` (new projects) | 20+yr | WPF / MAUI / Avalonia |
247
+ | ` packages.config ` | 10+yr | `PackageReference` in csproj |
248
+ | `Newtonsoft.Json` (for new System.Text.Json-capable projects) | — | `System.Text.Json` (.NET Core 3+) |
249
+
250
+ ### PHP
251
+
252
+ | Prehistoric | Age | Replacement |
253
+ |-------------|-----|-------------|
254
+ | `mysql_*` functions | 13yr | PDO or mysqli |
255
+ | `mcrypt` | 10yr | `openssl` / `sodium` (PHP 7.2+) |
256
+ | `PEAR` | 15+yr | Composer |
257
+ | `PHPUnit` < 9.x | — | PHPUnit 10.x / 11.x |
258
+
259
+ ## Built-In Preference Map
260
+
261
+ Before approving any third-party package, check if the language's standard
262
+ library already solves this. These are the most common cases where a package
263
+ is unnecessary:
264
+
265
+ ### JavaScript / TypeScript (Node 22+)
266
+ - `node:test` over `jest`/`mocha` (new projects)
267
+ - `node:sqlite` over `better-sqlite3` (Node 22.5+)
268
+ - `fetch`, `WebSocket`, `Web Crypto`, `AbortController`, `EventTarget` — all native
269
+ - `node:fs/promises` over `fs-extra`
270
+ - `URL` / `URLSearchParams` over `qs` / `query-string`
271
+
272
+ ### Python (3.12+)
273
+ - `pathlib` over `os.path` / `glob`
274
+ - `unittest` + `pytest` (pytest *is* still preferred, but unittest exists)
275
+ - `dataclasses` over `attrs` (simple cases)
276
+ - `tomllib` over `toml` (3.11+)
277
+ - `zoneinfo` over `pytz` (3.9+)
278
+ - `graphlib` over custom topological sort (3.9+)
279
+ - `importlib.resources` over `pkg_resources`
280
+
281
+ ### Rust (stable)
282
+ - `std::sync::LazyLock` over `lazy_static` / `once_cell` (1.80+)
283
+ - `std::sync::OnceLock` over `once_cell::sync::OnceCell`
284
+ - `std::cell::OnceCell` over `once_cell::unsync::OnceCell`
285
+ - `std::net` over `reqwest` (simple HTTP client cases)
286
+
287
+ ### Go (1.22+)
288
+ - `net/http` over third-party HTTP routers (for simple APIs)
289
+ - `log/slog` over `logrus` / `zap` (1.21+)
290
+ - `slices` / `maps` packages over `golang.org/x/exp` backports (1.21+)
291
+ - `cmp` / `math/rand/v2` / `unique` — all stdlib additions
292
+
293
+ ## Dead Package Criteria
140
294
 
141
295
  | Signal | Threshold | Action |
142
296
  |--------|-----------|--------|
143
297
  | No release | >2 years | Flag + check for replacement |
144
298
  | No release + critical CVEs | >1 year | REJECT automatically |
145
- | Deprecated on npm | Any | REJECT + suggest replacement |
299
+ | Deprecated/yanked on registry | Any | REJECT + suggest replacement |
146
300
  | Repository archived | Any | REJECT + suggest replacement |
147
- | <100 weekly downloads | Any | WARN + suggest more popular alternative |
301
+ | Low adoption | <500 weekly downloads (npm) / <100 stars + no recent commits | WARN + suggest alternative |
302
+ | Last commit | >3 years ago, no response to issues | WARN + flag as unmaintained |
148
303
 
149
- ## Output format
304
+ ## Output Format
150
305
 
151
306
  ```
152
307
  ### Tech Stack Validation — <package>
153
308
 
309
+ **Ecosystem**: <detected ecosystem>
154
310
  **Status**: APPROVED | REJECTED | NEEDS_INVESTIGATION
155
311
 
156
312
  **Package**: <name>@<version>
157
- **Source**: <npm registry / GitHub / web search — cite the URL>
313
+ **Registry**: <host + URL fetched>
158
314
  **Age**: <first release year> — <last release date>
159
315
  **Verdict**: 1–2 sentence explanation.
160
316
 
@@ -164,8 +320,8 @@ When REJECTED:
164
320
  **Migration**: <one concrete step>
165
321
 
166
322
  When APPROVED:
167
- **Install**: `pnpm add <name>@^<major>.<minor>.0`
168
- **Note**: <any caveats about the version>
323
+ **Install**: `<ecosystem install command>`
324
+ **Note**: <any caveats about the version, semver range, or compatibility>
169
325
  ```
170
326
 
171
327
  ## Skills in scope