arkaos 4.17.0 → 4.19.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/README.md +1 -1
- package/VERSION +1 -1
- package/arka/SKILL.md +1 -1
- package/config/agents-provenance.yaml +126 -0
- package/config/skills-provenance.yaml +6 -5
- package/core/agents/provenance.py +116 -0
- package/core/agents/registry_gen.py +75 -57
- package/core/cognition/insights/store.py +114 -7
- package/core/cognition/memory/schemas.py +45 -5
- package/core/hooks/pre_tool_use.py +59 -0
- package/core/provenance.py +108 -0
- package/core/skills/provenance.py +34 -72
- package/core/workflow/config_guard.py +176 -0
- package/core/workflow/transcript_scope.py +46 -0
- package/departments/dev/skills/click-path-audit/SKILL.md +76 -0
- package/departments/dev/skills/laravel-review/SKILL.md +82 -0
- package/departments/dev/skills/pr-test-analyzer/SKILL.md +77 -0
- package/departments/dev/skills/python-review/SKILL.md +80 -0
- package/departments/dev/skills/silent-failure-hunter/SKILL.md +70 -0
- package/departments/dev/skills/type-design-analyzer/SKILL.md +71 -0
- package/departments/dev/skills/typescript-review/SKILL.md +81 -0
- package/departments/dev/skills/vue-review/SKILL.md +80 -0
- package/knowledge/agents-registry-v2.json +259 -1
- package/knowledge/skills-manifest.json +105 -1
- package/package.json +1 -1
- package/pyproject.toml +1 -1
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: dev/click-path-audit
|
|
3
|
+
description: >
|
|
4
|
+
Simulates every interactive handler call-by-call to find bugs a normal
|
|
5
|
+
read skips over — shared-state side effects, handlers that silently undo
|
|
6
|
+
each other, and async races — then checks the final UI state matches
|
|
7
|
+
what the control promises. TRIGGER: "/dev click-path-audit", "the button
|
|
8
|
+
does nothing", "state side effects", "handlers cancel each other", "why
|
|
9
|
+
is the UI wrong after clicking", "o botão não faz nada", "audita o fluxo
|
|
10
|
+
de cliques"; run on an interactive component whose behaviour is wrong but
|
|
11
|
+
whose code looks right. SKIP: general pre-merge review ->
|
|
12
|
+
dev/code-review wins; visual/layout/brand review ->
|
|
13
|
+
brand/design-review wins.
|
|
14
|
+
allowed-tools: [Read, Grep, Glob]
|
|
15
|
+
metadata:
|
|
16
|
+
origin: arkaos
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
# Click-Path Audit — `/dev click-path-audit`
|
|
20
|
+
|
|
21
|
+
> **Agent:** Diana (Senior Frontend Developer) | **Framework:** Handler state-tracing, shared-state side-effect analysis
|
|
22
|
+
|
|
23
|
+
Some interface bugs survive every check that looks at one thing at a time.
|
|
24
|
+
Each handler compiles, each function returns the right type, each call
|
|
25
|
+
works when you test it alone — and the button still does the wrong thing,
|
|
26
|
+
because the second call quietly resets the state the first one set. This
|
|
27
|
+
lens catches those by simulating the handler on paper: it walks the calls
|
|
28
|
+
in the order they run and tracks what each reads, writes, and resets in
|
|
29
|
+
shared state, so a cancelling side effect shows up before a user ever
|
|
30
|
+
clicks.
|
|
31
|
+
|
|
32
|
+
## The bug this catches
|
|
33
|
+
|
|
34
|
+
An "Apply filters" button called `setFilters(next)` and then, to close the
|
|
35
|
+
panel, `resetPanel()`. Each worked alone — but `resetPanel` cleared the
|
|
36
|
+
draft filter state as part of tidying up, so the store ended with the old
|
|
37
|
+
filters and the list never changed. No type error, no crash, no failing
|
|
38
|
+
unit test; the two setters simply fought and the second won. Walking the
|
|
39
|
+
handler's calls in order puts the cleared write next to the one it
|
|
40
|
+
cancelled, and the bug is visible without ever running the app.
|
|
41
|
+
|
|
42
|
+
## Process
|
|
43
|
+
|
|
44
|
+
For every interactive touchpoint in scope (`onClick`, `onSubmit`, `onChange`, effects):
|
|
45
|
+
|
|
46
|
+
1. **Identify** the handler.
|
|
47
|
+
2. **Trace** each call it makes, in order.
|
|
48
|
+
3. For each call record: what shared state it **reads**, what it **writes**, and any **side effect** — especially a state it clears or resets that it does not obviously own.
|
|
49
|
+
4. **Check** whether any later call undoes a state change an earlier call made.
|
|
50
|
+
5. **Check** the final state matches what the control's label promises.
|
|
51
|
+
6. **Check** for races — async calls whose resolution order changes the outcome (a stale response overwriting a fresh one).
|
|
52
|
+
|
|
53
|
+
## Proactive Triggers
|
|
54
|
+
|
|
55
|
+
Surface these WITHOUT being asked:
|
|
56
|
+
|
|
57
|
+
- two calls in one handler that write the same store slice → which one wins, and is that intended
|
|
58
|
+
- a setter with a side effect that resets unrelated state (a `select`/`reset`/`clear` that touches more than its name implies) → the earlier change it silently undoes
|
|
59
|
+
- an `await` inside a handler with no guard against an out-of-order resolution → the stale-overwrite race
|
|
60
|
+
|
|
61
|
+
## Output
|
|
62
|
+
|
|
63
|
+
```markdown
|
|
64
|
+
## Click-Path Report
|
|
65
|
+
|
|
66
|
+
**Scope:** {component / area audited}
|
|
67
|
+
|
|
68
|
+
### {control / handler} — {file}:{line}
|
|
69
|
+
| # | Call | Reads | Writes | Side effect |
|
|
70
|
+
|---|------|-------|--------|-------------|
|
|
71
|
+
| 1 | {fn} | {state} | {state} | {reset/clear, or none} |
|
|
72
|
+
| 2 | {fn} | {state} | {state} | {undoes call 1's write?} |
|
|
73
|
+
|
|
74
|
+
**Promised by label:** {what the user expects} · **Actual final state:** {what happens}
|
|
75
|
+
**Verdict:** {works / silently broken} · **Fix:** {reorder, isolate the side effect, guard the race}
|
|
76
|
+
```
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: dev/laravel-review
|
|
3
|
+
description: >
|
|
4
|
+
Laravel/PHP review against ArkaOS conventions — mass assignment, N+1
|
|
5
|
+
queries, Blade XSS, business logic leaking into controllers, missing
|
|
6
|
+
FormRequests, and strict-types gaps — with the fix each one needs.
|
|
7
|
+
TRIGGER: "/dev laravel-review", "review this Laravel", "review the PHP",
|
|
8
|
+
"revê este controller", "revê o Eloquent", "isto está seguro em
|
|
9
|
+
Laravel?", any diff touching *.php, Blade, or Eloquent models. SKIP:
|
|
10
|
+
language-agnostic pre-merge review -> dev/code-review wins; database
|
|
11
|
+
schema/migration design -> dev/db-design wins; a security audit of the
|
|
12
|
+
whole app -> dev/security-audit wins.
|
|
13
|
+
allowed-tools: [Read, Grep, Glob, Bash]
|
|
14
|
+
metadata:
|
|
15
|
+
origin: arkaos
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
# Laravel Review — `/dev laravel-review`
|
|
19
|
+
|
|
20
|
+
> **Agent:** Gonçalo (Laravel Specialist) | **Framework:** Laravel conventions, OWASP, ArkaOS Services+Repositories standard
|
|
21
|
+
|
|
22
|
+
Laravel makes the wrong thing easy: `create($request->all())` is one line
|
|
23
|
+
and a mass-assignment hole, an Eloquent relation in a Blade loop is one
|
|
24
|
+
property access and an N+1, `{!! $x !!}` is shorter than the escaped form
|
|
25
|
+
and an XSS. This review reads a PHP diff for the specific ways the
|
|
26
|
+
framework's convenience turns into a defect, and holds it to the ArkaOS
|
|
27
|
+
Laravel standard — Services and Repositories, FormRequests everywhere,
|
|
28
|
+
`declare(strict_types=1)`, not just to PSR-12.
|
|
29
|
+
|
|
30
|
+
## Review Priorities
|
|
31
|
+
|
|
32
|
+
### Critical — Security
|
|
33
|
+
- **Mass assignment**: `create($request->all())` or `$guarded = []` → whitelist `$fillable`, or pass `$request->validated()` from a FormRequest.
|
|
34
|
+
- **SQL injection**: `DB::raw()`/`whereRaw()`/string-interpolated queries with user input → parameterised bindings or Eloquent.
|
|
35
|
+
- **Blade XSS**: `{!! $userInput !!}` without HTMLPurifier → `{{ }}`, or purify explicitly.
|
|
36
|
+
- **Command/path**: `exec`/`shell_exec`/`system` or `Storage` paths from user input → validate and sanitise.
|
|
37
|
+
- **Unvalidated uploads**: no MIME/size/extension check on file inputs.
|
|
38
|
+
- **Weak crypto / secrets**: MD5 for passwords, hardcoded keys.
|
|
39
|
+
|
|
40
|
+
### Critical — Error handling
|
|
41
|
+
- **Swallowed exceptions**: `catch (\Throwable $e) {}` with no log and no re-throw.
|
|
42
|
+
- **Missing validation**: a controller action with no FormRequest and no inline rules.
|
|
43
|
+
|
|
44
|
+
### High — ArkaOS Laravel standard
|
|
45
|
+
- **Business logic in controllers** → extract to a Service or Action; the controller orchestrates, it does not decide.
|
|
46
|
+
- **Data access outside a Repository** where the ecosystem uses them.
|
|
47
|
+
- **No FormRequest** on a write endpoint → `$request->validated()`, never `$request->all()`.
|
|
48
|
+
- **Missing `declare(strict_types=1)`** in non-view PHP; untyped public method params/returns.
|
|
49
|
+
- **N+1**: an Eloquent relation accessed in a loop or serialisation with no `with()`/`$with`.
|
|
50
|
+
- **Missing `$fillable`/`$casts`** on models; **missing Feature test** (`RefreshDatabase`) on the changed behaviour.
|
|
51
|
+
|
|
52
|
+
## Process
|
|
53
|
+
|
|
54
|
+
1. `git diff -- '*.php' '*.blade.php'` to scope the change.
|
|
55
|
+
2. Run PHPStan/Pint if configured — read their output, do not just report their absence.
|
|
56
|
+
3. Read each changed controller/model/service against the priorities, heaviest first.
|
|
57
|
+
|
|
58
|
+
## Proactive Triggers
|
|
59
|
+
|
|
60
|
+
Surface these WITHOUT being asked:
|
|
61
|
+
|
|
62
|
+
- `$request->all()` reaching a `create`/`update`/`fill` → the mass-assignment hole; name the fields it exposes
|
|
63
|
+
- a relation accessed inside `@foreach` or an API Resource with no eager load → the N+1 and the `with()` that fixes it
|
|
64
|
+
- a controller method over ~15 lines carrying query + business logic → the Service/Action to extract
|
|
65
|
+
|
|
66
|
+
## Output
|
|
67
|
+
|
|
68
|
+
```markdown
|
|
69
|
+
## Laravel Review
|
|
70
|
+
|
|
71
|
+
**Scope:** {changed PHP / Blade}
|
|
72
|
+
**Verdict:** {APPROVED / CHANGES REQUESTED}
|
|
73
|
+
|
|
74
|
+
### Critical
|
|
75
|
+
- [ ] {file}:{line} — {the hole} → {the fix}
|
|
76
|
+
|
|
77
|
+
### High (ArkaOS standard)
|
|
78
|
+
- [ ] {file}:{line} — {the convention broken} → {the fix}
|
|
79
|
+
|
|
80
|
+
### Positive
|
|
81
|
+
{what follows the standard well}
|
|
82
|
+
```
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: dev/pr-test-analyzer
|
|
3
|
+
description: >
|
|
4
|
+
Judges whether a PR's tests would catch the change breaking — maps
|
|
5
|
+
changed code to its tests, finds untested paths and edge cases, flags
|
|
6
|
+
assertion-free and flaky tests, and ranks the gaps by blast radius.
|
|
7
|
+
TRIGGER: "/dev pr-test-analyzer", "test coverage of this PR", "are these
|
|
8
|
+
tests enough", "behavioural coverage", "test gaps", "os testes cobrem
|
|
9
|
+
isto?", "isto está bem testado?"; run on a diff before approving its
|
|
10
|
+
merge. SKIP: general code review -> dev/code-review wins; writing the
|
|
11
|
+
missing tests -> dev/tdd-cycle wins; error-handling review ->
|
|
12
|
+
dev/silent-failure-hunter wins.
|
|
13
|
+
allowed-tools: [Read, Grep, Glob, Bash]
|
|
14
|
+
metadata:
|
|
15
|
+
origin: arkaos
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
# PR Test Analyzer — `/dev pr-test-analyzer`
|
|
19
|
+
|
|
20
|
+
> **Agent:** Rita (QA Engineer) | **Framework:** Behavioural coverage, test-quality over line-coverage
|
|
21
|
+
|
|
22
|
+
Coverage is a measure of which lines ran, and it is routinely mistaken for
|
|
23
|
+
a measure of whether the change is safe. A PR can add a feature, run every
|
|
24
|
+
new line through one happy-path test that asserts almost nothing, and post
|
|
25
|
+
a green 100%. This lens reads the diff and its tests side by side and holds
|
|
26
|
+
them to the only standard that matters at merge time: if the change were
|
|
27
|
+
wrong, would a test go red?
|
|
28
|
+
|
|
29
|
+
## Analysis
|
|
30
|
+
|
|
31
|
+
### 1. Map changed code to tests
|
|
32
|
+
- List the functions, classes, and branches the diff added or altered.
|
|
33
|
+
- Locate the tests that exercise each. Name the changed paths with **no** test.
|
|
34
|
+
|
|
35
|
+
### 2. Behavioural coverage
|
|
36
|
+
- Does each new behaviour have a test that would fail if the behaviour broke?
|
|
37
|
+
- Are the edge cases covered — empty input, boundary values, the error path, not just the success path?
|
|
38
|
+
- Are the integrations the change touches (db, queue, external call) exercised, or only mocked away?
|
|
39
|
+
|
|
40
|
+
### 3. Test quality
|
|
41
|
+
- Flag tests that assert nothing beyond "it did not throw" — a green test that proves nothing.
|
|
42
|
+
- Flag flaky patterns: time/order dependence, shared mutable state, sleeps.
|
|
43
|
+
- Check that test names describe the behaviour, so a failure reads as a spec.
|
|
44
|
+
|
|
45
|
+
### 4. Rank the gaps
|
|
46
|
+
Rate each gap by the blast radius of the bug it would let ship:
|
|
47
|
+
critical (data loss, auth, money), important (a real feature path),
|
|
48
|
+
nice-to-have (a defensive branch unlikely to trigger).
|
|
49
|
+
|
|
50
|
+
## Proactive Triggers
|
|
51
|
+
|
|
52
|
+
Surface these WITHOUT being asked:
|
|
53
|
+
|
|
54
|
+
- a changed function with no test at all → critical or important by its blast radius; name it
|
|
55
|
+
- a new test with no assertion (or only `assert not raises`) → it proves nothing; say what it should assert
|
|
56
|
+
- an error/exception path added in the diff with only the happy path tested → the failure that ships untested
|
|
57
|
+
|
|
58
|
+
## Output
|
|
59
|
+
|
|
60
|
+
```markdown
|
|
61
|
+
## PR Test Report
|
|
62
|
+
|
|
63
|
+
**Diff:** {files / functions changed}
|
|
64
|
+
**Verdict:** {tests adequate to merge? yes / gaps below}
|
|
65
|
+
|
|
66
|
+
### Coverage summary
|
|
67
|
+
{what is covered well, in one or two lines}
|
|
68
|
+
|
|
69
|
+
### Critical gaps
|
|
70
|
+
- {file}:{func} — {the behaviour with no failing test} → {the test to add}
|
|
71
|
+
|
|
72
|
+
### Test-quality issues
|
|
73
|
+
- {file}:{test} — {assertion-free / flaky} → {fix}
|
|
74
|
+
|
|
75
|
+
### Positive
|
|
76
|
+
{what the tests do genuinely well}
|
|
77
|
+
```
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: dev/python-review
|
|
3
|
+
description: >
|
|
4
|
+
Python review against ArkaOS conventions — missing type hints, mutable
|
|
5
|
+
default arguments, bare excepts, unvalidated boundaries, injection, and
|
|
6
|
+
Pydantic/FastAPI mistakes — with the fix each needs. TRIGGER: "/dev
|
|
7
|
+
python-review", "review this Python", "review the FastAPI", "revê o
|
|
8
|
+
Python", "revê este endpoint", "isto está pythonico?", any diff touching
|
|
9
|
+
*.py. SKIP: language-agnostic pre-merge review -> dev/code-review wins;
|
|
10
|
+
pytest coverage of the change -> dev/pr-test-analyzer wins; swallowed-error
|
|
11
|
+
hunt across the codebase -> dev/silent-failure-hunter wins.
|
|
12
|
+
allowed-tools: [Read, Grep, Glob, Bash]
|
|
13
|
+
metadata:
|
|
14
|
+
origin: arkaos
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
# Python Review — `/dev python-review`
|
|
18
|
+
|
|
19
|
+
> **Agent:** Diogo (Python Backend Specialist) | **Framework:** Type hints, Pydantic validation, PEP 8, ArkaOS core conventions
|
|
20
|
+
|
|
21
|
+
Python trusts the author, and that trust is where the bugs live: a
|
|
22
|
+
mutable default argument shared across every call, a bare `except` that
|
|
23
|
+
buries the traceback, a function with no type hints that the checker
|
|
24
|
+
cannot help. This review reads a Python diff against the ArkaOS core
|
|
25
|
+
standard — type hints on every signature, Pydantic at the boundary,
|
|
26
|
+
functions under thirty lines — and for the runtime traps the interpreter
|
|
27
|
+
will happily let ship.
|
|
28
|
+
|
|
29
|
+
## Review Priorities
|
|
30
|
+
|
|
31
|
+
### Critical — Correctness traps
|
|
32
|
+
- **Mutable default argument**: `def f(x=[])` / `={}` → default to `None`, build inside.
|
|
33
|
+
- **Bare `except:` / `except Exception: pass`** → catch the specific type, log, re-raise or handle.
|
|
34
|
+
- **Late-binding closure in a loop** capturing the loop variable → bind explicitly.
|
|
35
|
+
|
|
36
|
+
### Critical — Boundary & security
|
|
37
|
+
- **Unvalidated input** used as a trusted shape → a Pydantic model at the boundary, not a raw dict.
|
|
38
|
+
- **Injection**: f-string/`%`-built SQL or `subprocess`/`os.system` with user input → parameterise / `shlex`, never interpolate.
|
|
39
|
+
- **`eval`/`exec`/`pickle`** on untrusted data; hardcoded secrets.
|
|
40
|
+
|
|
41
|
+
### High — ArkaOS core standard
|
|
42
|
+
- **Missing type hints** on a public signature → hint params and return.
|
|
43
|
+
- **A function over 30 lines** or nesting past 3 → decompose (`.claude/rules/python-core.md`).
|
|
44
|
+
- **Pydantic misuse**: validation logic in a route instead of a `field_validator`; a model that admits an illegal state.
|
|
45
|
+
- **Dataclass over Pydantic** where validation is needed; a broad `dict`/`Any` where a model belongs.
|
|
46
|
+
|
|
47
|
+
### High — Idiom
|
|
48
|
+
- A manual index loop where a comprehension/`enumerate` reads clearer; a `try` used for flow control; string concatenation in a hot loop.
|
|
49
|
+
|
|
50
|
+
## Process
|
|
51
|
+
|
|
52
|
+
1. `git diff -- '*.py'` to scope the change.
|
|
53
|
+
2. Run `ruff`/`mypy`/`pytest` if configured — read the output, do not just note their absence.
|
|
54
|
+
3. Read each changed function against the priorities, correctness traps first.
|
|
55
|
+
|
|
56
|
+
## Proactive Triggers
|
|
57
|
+
|
|
58
|
+
Surface these WITHOUT being asked:
|
|
59
|
+
|
|
60
|
+
- a mutable default argument in the diff → the shared-state bug across calls
|
|
61
|
+
- a `dict` passed through several layers as if typed → the Pydantic model that should guard the boundary
|
|
62
|
+
- a function that grew past 30 lines in the diff → the seam to split it on
|
|
63
|
+
|
|
64
|
+
## Output
|
|
65
|
+
|
|
66
|
+
```markdown
|
|
67
|
+
## Python Review
|
|
68
|
+
|
|
69
|
+
**Scope:** {changed Python}
|
|
70
|
+
**Verdict:** {APPROVED / CHANGES REQUESTED}
|
|
71
|
+
|
|
72
|
+
### Critical
|
|
73
|
+
- [ ] {file}:{line} — {the trap} → {the fix}
|
|
74
|
+
|
|
75
|
+
### High (ArkaOS standard)
|
|
76
|
+
- [ ] {file}:{line} — {the convention broken} → {the fix}
|
|
77
|
+
|
|
78
|
+
### Positive
|
|
79
|
+
{what is idiomatic and well-typed}
|
|
80
|
+
```
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: dev/silent-failure-hunter
|
|
3
|
+
description: >
|
|
4
|
+
Hunts silent failures — swallowed exceptions, errors coerced to null,
|
|
5
|
+
fallbacks that mask a broken path, lost stack traces, and unguarded
|
|
6
|
+
network/file/db/transaction calls — and reports the concrete failure
|
|
7
|
+
each one hides, ranked by blast radius. TRIGGER: "/dev
|
|
8
|
+
silent-failure-hunter", "silent failures", "swallowed errors", "empty
|
|
9
|
+
catch", "error handling review", "falhas silenciosas", "erros
|
|
10
|
+
engolidos", "isto está a falhar em silêncio?"; run on the error paths
|
|
11
|
+
of any change touching I/O, network, db, or transactions. SKIP: general
|
|
12
|
+
pre-merge review -> dev/code-review wins; test coverage of the change ->
|
|
13
|
+
dev/pr-test-analyzer wins.
|
|
14
|
+
allowed-tools: [Read, Grep, Glob]
|
|
15
|
+
metadata:
|
|
16
|
+
origin: arkaos
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
# Silent Failure Hunter — `/dev silent-failure-hunter`
|
|
20
|
+
|
|
21
|
+
> **Agent:** Rita (QA Engineer) | **Framework:** Defensive error handling, fail-loud discipline
|
|
22
|
+
|
|
23
|
+
Every catch block is a decision about who finds out when something breaks.
|
|
24
|
+
Too many of them decide that nobody does: the exception is caught and
|
|
25
|
+
dropped, the failed call returns an empty list, the timeout is swallowed
|
|
26
|
+
and the caller carries on with half the data. This lens assumes the worst
|
|
27
|
+
about each one and asks a single question of it — when this path fails at
|
|
28
|
+
runtime, who learns, and how?
|
|
29
|
+
|
|
30
|
+
## Hunt Targets
|
|
31
|
+
|
|
32
|
+
| # | Class | What to flag |
|
|
33
|
+
|---|-------|--------------|
|
|
34
|
+
| 1 | Swallowed errors | `catch {}`, `except: pass`, an error coerced to `null`/`[]`/`0` with no log and no re-raise |
|
|
35
|
+
| 2 | Inadequate logging | logged at the wrong severity, logged without the context to diagnose it, log-and-continue where the caller needed to know |
|
|
36
|
+
| 3 | Masking fallbacks | a default that hides a real failure — `.catch(() => [])`, `?? {}` over a failed fetch — so the bug surfaces three layers downstream instead of here |
|
|
37
|
+
| 4 | Broken propagation | a lost stack trace, a generic re-raise that drops the cause, an `async` path with no `await` on the error, a promise with no rejection handler |
|
|
38
|
+
| 5 | Unguarded boundaries | a network/file/db call with no timeout and no error handling; transactional work with no rollback on the failure path |
|
|
39
|
+
|
|
40
|
+
## Process
|
|
41
|
+
|
|
42
|
+
1. Grep the diff (or the named area) for the target patterns — `catch`, `except`, `.catch(`, `try`, `?? `, bare `return null`.
|
|
43
|
+
2. For each hit, answer one question: **if this path fails at runtime, who finds out, and how?** If the answer is "nobody" or "a confused engineer three files away", it is a finding.
|
|
44
|
+
3. Trace the caller once — a swallowed error is only safe if the caller genuinely does not need to know, and that is rare.
|
|
45
|
+
4. Rank by blast radius: a masked failure on a payment or data-write path is critical; a swallowed log flush is minor.
|
|
46
|
+
|
|
47
|
+
## Proactive Triggers
|
|
48
|
+
|
|
49
|
+
Surface these WITHOUT being asked:
|
|
50
|
+
|
|
51
|
+
- an empty catch on any I/O, network, or database call → critical; name what fails silently
|
|
52
|
+
- `.catch(() => <default>)` or `except: pass` on a data-fetch path → the downstream bug this plants is worse than the crash it prevents
|
|
53
|
+
- a re-raise that drops the original exception (`raise NewError()` with no `from`) → the stack trace the on-call engineer needs is gone
|
|
54
|
+
|
|
55
|
+
## Output
|
|
56
|
+
|
|
57
|
+
```markdown
|
|
58
|
+
## Silent Failure Report
|
|
59
|
+
|
|
60
|
+
**Scope:** {files / diff reviewed}
|
|
61
|
+
**Findings:** {n} ({c} critical, {h} high, {m} medium)
|
|
62
|
+
|
|
63
|
+
### {SEVERITY} — {file}:{line}
|
|
64
|
+
- **Hides:** {the concrete runtime failure that goes unseen}
|
|
65
|
+
- **Impact:** {who is affected and how far downstream the real bug surfaces}
|
|
66
|
+
- **Fix:** {the specific change — log with context, re-raise with cause, add the timeout}
|
|
67
|
+
|
|
68
|
+
### Clean
|
|
69
|
+
{paths checked that handle failure honestly — say so, briefly}
|
|
70
|
+
```
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: dev/type-design-analyzer
|
|
3
|
+
description: >
|
|
4
|
+
Scores whether a module's types make illegal states unrepresentable —
|
|
5
|
+
across encapsulation, invariant expression, invariant usefulness, and
|
|
6
|
+
type-system enforcement — and names the concrete bug each weak type
|
|
7
|
+
lets through. TRIGGER: "/dev type-design-analyzer", "type design",
|
|
8
|
+
"illegal states", "make invalid states unrepresentable", "domain
|
|
9
|
+
modelling review", "revê o design dos tipos", "estes tipos estão bem
|
|
10
|
+
desenhados?"; run on the public types of a module or a domain model.
|
|
11
|
+
SKIP: general code review -> dev/code-review wins; the data-model
|
|
12
|
+
schema of a new feature -> dev/db-design or dev/ddd-model wins.
|
|
13
|
+
allowed-tools: [Read, Grep, Glob]
|
|
14
|
+
metadata:
|
|
15
|
+
origin: arkaos
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
# Type Design Analyzer — `/dev type-design-analyzer`
|
|
19
|
+
|
|
20
|
+
> **Agent:** Gabriel (Software Architect) | **Framework:** Make-illegal-states-unrepresentable, type-driven design
|
|
21
|
+
|
|
22
|
+
The strongest bug fix is the one that makes the bug impossible to write.
|
|
23
|
+
A type that admits only valid values turns a whole class of runtime error
|
|
24
|
+
into a compile error nobody can ship past. This lens reads the shape of a
|
|
25
|
+
module's data — its enums, its models, its bounded fields — and asks what
|
|
26
|
+
invalid state that shape still permits, because every permitted invalid
|
|
27
|
+
state is a bug waiting for the caller who constructs it.
|
|
28
|
+
|
|
29
|
+
## Evaluation Criteria
|
|
30
|
+
|
|
31
|
+
For each type in scope, score four dimensions and justify each score
|
|
32
|
+
with the specific state it does or does not prevent.
|
|
33
|
+
|
|
34
|
+
| Dimension | The question |
|
|
35
|
+
|-----------|--------------|
|
|
36
|
+
| **Encapsulation** | Are internals hidden? Can an invariant be violated from outside — a public field mutated past a bound, a list appended to past its cap? |
|
|
37
|
+
| **Invariant expression** | Do the types encode the business rule? Is an impossible state (a shipped order with no address, a negative price) representable at all? |
|
|
38
|
+
| **Invariant usefulness** | Do these invariants prevent *real* bugs in this domain, or are they ceremony that constrains nothing anyone would get wrong? |
|
|
39
|
+
| **Enforcement** | Is the invariant enforced by the type system, or by a convention with an easy escape hatch (a raw `str` where an enum belongs, an `Optional` that is never `None` in practice but the checker cannot know)? |
|
|
40
|
+
|
|
41
|
+
## Process
|
|
42
|
+
|
|
43
|
+
1. Grep the module for its public types — dataclasses, Pydantic models, enums, TypedDicts, the domain nouns.
|
|
44
|
+
2. For each, ask the one diagnostic question: **what invalid value can I construct with this type that the domain forbids?** Every answer is a design gap.
|
|
45
|
+
3. Prefer the fix that moves the check to construction time — a validator, a narrower type, a smart constructor — over a runtime guard the caller must remember.
|
|
46
|
+
|
|
47
|
+
## Proactive Triggers
|
|
48
|
+
|
|
49
|
+
Surface these WITHOUT being asked:
|
|
50
|
+
|
|
51
|
+
- a domain value carried as a bare `str`/`int` where an enum or a bounded newtype belongs → the illegal value it now admits
|
|
52
|
+
- an `Optional`/nullable field that is never legitimately empty → make it required and delete the downstream `None` checks
|
|
53
|
+
- a boolean pair that encodes a state machine (`is_draft` + `is_published` both settable true) → the impossible state it allows; replace with one enum
|
|
54
|
+
|
|
55
|
+
## Output
|
|
56
|
+
|
|
57
|
+
```markdown
|
|
58
|
+
## Type Design Report
|
|
59
|
+
|
|
60
|
+
**Scope:** {module / types reviewed}
|
|
61
|
+
|
|
62
|
+
### {type name} — {file}:{line}
|
|
63
|
+
| Dimension | Score /5 | Why |
|
|
64
|
+
|-----------|---------|-----|
|
|
65
|
+
| Encapsulation | {n} | {the state it lets outside code violate, or "hidden"} |
|
|
66
|
+
| Invariant expression | {n} | {the impossible state it does/does not prevent} |
|
|
67
|
+
| Invariant usefulness | {n} | {real bug prevented, or ceremony} |
|
|
68
|
+
| Enforcement | {n} | {type-enforced, or the escape hatch} |
|
|
69
|
+
|
|
70
|
+
**Overall:** {one line} · **Fix:** {the narrower type / validator / smart constructor}
|
|
71
|
+
```
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: dev/typescript-review
|
|
3
|
+
description: >
|
|
4
|
+
TypeScript/Node review for the holes the compiler waves through — `any`
|
|
5
|
+
and unsafe casts, unhandled promise rejections, missing input validation
|
|
6
|
+
at the boundary, and injection in queries or shell calls — with the fix
|
|
7
|
+
each needs. TRIGGER: "/dev typescript-review", "review this TS", "review
|
|
8
|
+
the Node", "revê o TypeScript", "revê este endpoint Node", "isto está
|
|
9
|
+
type-safe?", any diff touching *.ts/*.tsx server or API code. SKIP:
|
|
10
|
+
language-agnostic pre-merge review -> dev/code-review wins; React/Vue
|
|
11
|
+
component rendering bugs -> dev/vue-review or dev/click-path-audit wins;
|
|
12
|
+
type-design depth -> dev/type-design-analyzer wins.
|
|
13
|
+
allowed-tools: [Read, Grep, Glob, Bash]
|
|
14
|
+
metadata:
|
|
15
|
+
origin: arkaos
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
# TypeScript Review — `/dev typescript-review`
|
|
19
|
+
|
|
20
|
+
> **Agent:** Vera (Node.js / TypeScript Backend Specialist) | **Framework:** Type safety, async correctness, boundary validation
|
|
21
|
+
|
|
22
|
+
TypeScript's guarantees stop at the edges of the program, and that is
|
|
23
|
+
where the bugs get in: an `any` erases every check downstream, a JSON
|
|
24
|
+
body typed as its interface is a lie until something validates it, a
|
|
25
|
+
floating promise swallows the error the caller needed. This review reads
|
|
26
|
+
a TS diff for the places the type system was told to look away, and for
|
|
27
|
+
the async and boundary mistakes no compiler flags.
|
|
28
|
+
|
|
29
|
+
## Review Priorities
|
|
30
|
+
|
|
31
|
+
### Critical — Type safety holes
|
|
32
|
+
- **`any` / `as` casts** on external data → validate into a real type (Zod, a type guard); an `any` is an unchecked check for everything it touches.
|
|
33
|
+
- **Non-null `!`** on a value that can be null at runtime → handle the null.
|
|
34
|
+
- **`@ts-ignore` / `@ts-expect-error`** hiding a real type error → fix the type, do not silence it.
|
|
35
|
+
|
|
36
|
+
### Critical — Async correctness
|
|
37
|
+
- **Floating promise**: an `async` call with no `await` and no `.catch` → the rejection is lost.
|
|
38
|
+
- **`await` in a loop** where `Promise.all` is correct → serial latency; and the reverse, unbounded `Promise.all` over a large list.
|
|
39
|
+
- **Missing try/catch** around an `await` on I/O, or a catch that swallows.
|
|
40
|
+
|
|
41
|
+
### Critical — Boundary
|
|
42
|
+
- **Unvalidated input**: a request body/query/param used as its TS type with no runtime schema → validate at the boundary.
|
|
43
|
+
- **Injection**: string-built SQL or `exec`/`child_process` with user input → parameterise / sanitise.
|
|
44
|
+
- **Secrets**: hardcoded keys; secrets logged.
|
|
45
|
+
|
|
46
|
+
### High — Standards
|
|
47
|
+
- Public function signatures untyped or returning inferred `any`.
|
|
48
|
+
- `Promise<void>` swallowing a result the caller needs; error thrown as a bare string.
|
|
49
|
+
- Mutating a shared object where an immutable update belongs.
|
|
50
|
+
|
|
51
|
+
## Process
|
|
52
|
+
|
|
53
|
+
1. `git diff -- '*.ts' '*.tsx'` to scope the change.
|
|
54
|
+
2. Run `tsc --noEmit` and the linter if configured — read the output.
|
|
55
|
+
3. Read each changed handler/service for the priorities, type holes first.
|
|
56
|
+
|
|
57
|
+
## Proactive Triggers
|
|
58
|
+
|
|
59
|
+
Surface these WITHOUT being asked:
|
|
60
|
+
|
|
61
|
+
- a request body used as `req.body as SomeType` with no validation → the boundary hole and the schema that closes it
|
|
62
|
+
- an `async` function called with no `await`/`.catch` → the floating rejection
|
|
63
|
+
- an `any` introduced in the diff → what it stops the compiler from checking downstream
|
|
64
|
+
|
|
65
|
+
## Output
|
|
66
|
+
|
|
67
|
+
```markdown
|
|
68
|
+
## TypeScript Review
|
|
69
|
+
|
|
70
|
+
**Scope:** {changed TS}
|
|
71
|
+
**Verdict:** {APPROVED / CHANGES REQUESTED}
|
|
72
|
+
|
|
73
|
+
### Critical
|
|
74
|
+
- [ ] {file}:{line} — {the hole} → {the fix}
|
|
75
|
+
|
|
76
|
+
### High
|
|
77
|
+
- [ ] {file}:{line} — {the issue} → {the fix}
|
|
78
|
+
|
|
79
|
+
### Positive
|
|
80
|
+
{what is genuinely type-safe and correct}
|
|
81
|
+
```
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: dev/vue-review
|
|
3
|
+
description: >
|
|
4
|
+
Vue 3 / Nuxt review for the framework's own traps — lost reactivity,
|
|
5
|
+
SSR hydration mismatches, missing keys, uncleaned watchers, and props
|
|
6
|
+
mutated in place — with the fix each needs. Composition API and
|
|
7
|
+
TypeScript assumed. TRIGGER: "/dev vue-review", "review this Vue",
|
|
8
|
+
"review the Nuxt", "revê este componente Vue", "revê o composable",
|
|
9
|
+
"porque é que a reactividade não funciona?", any diff touching
|
|
10
|
+
*.vue/composables. SKIP: language-agnostic review -> dev/code-review
|
|
11
|
+
wins; a handler-ordering/state-cancellation bug -> dev/click-path-audit
|
|
12
|
+
wins; visual/brand review -> brand/design-review wins.
|
|
13
|
+
allowed-tools: [Read, Grep, Glob]
|
|
14
|
+
metadata:
|
|
15
|
+
origin: arkaos
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
# Vue Review — `/dev vue-review`
|
|
19
|
+
|
|
20
|
+
> **Agent:** Diana (Senior Frontend Developer) | **Framework:** Vue 3 Composition API, Nuxt SSR, reactivity correctness
|
|
21
|
+
|
|
22
|
+
Most Vue bugs are not wrong logic — they are the reactivity system doing
|
|
23
|
+
exactly what you told it, which was not what you meant. Destructure a
|
|
24
|
+
`reactive` object and the binding is gone; read a value during SSR that
|
|
25
|
+
only exists on the client and hydration tears; forget a `:key` and the
|
|
26
|
+
list reuses the wrong DOM. This review reads a Vue/Nuxt diff for those
|
|
27
|
+
framework-specific traps, on the assumption of Composition API and
|
|
28
|
+
TypeScript throughout.
|
|
29
|
+
|
|
30
|
+
## Review Priorities
|
|
31
|
+
|
|
32
|
+
### Critical — Reactivity
|
|
33
|
+
- **Destructured reactivity**: `const { x } = reactive(...)` or a destructured prop → `toRefs`/`toRef`, or access through the object; the destructured copy is inert.
|
|
34
|
+
- **Ref unwrapped wrong**: `.value` missing in script, or added in template; a `ref` stored in a plain object it is read from without unwrapping.
|
|
35
|
+
- **Prop mutated in place** → emit an event or use a local copy; props are one-way.
|
|
36
|
+
|
|
37
|
+
### Critical — SSR / Nuxt hydration
|
|
38
|
+
- **Client-only value read during SSR** (`window`, `localStorage`, `Date.now()` in setup) → guard with `import.meta.client`/`onMounted`; the mismatch tears hydration.
|
|
39
|
+
- **Non-deterministic render** between server and client (random, unstable order).
|
|
40
|
+
- **Data fetched without `useAsyncData`/`useFetch`** where SSR needs it → double fetch or hydration gap.
|
|
41
|
+
|
|
42
|
+
### High — Correctness
|
|
43
|
+
- **Missing `:key`** on a `v-for`, or `:key="index"` on a reorderable list → wrong-DOM reuse.
|
|
44
|
+
- **Watcher/interval/listener not cleaned up** in `onUnmounted` → leak.
|
|
45
|
+
- **`v-if` + `v-for` on the same element**; heavy work in a computed with side effects.
|
|
46
|
+
|
|
47
|
+
### High — Standards
|
|
48
|
+
- Options API in new code where the project is Composition API; `any`-typed props; a composable that is not prefixed `use` or leaks state across instances.
|
|
49
|
+
|
|
50
|
+
## Process
|
|
51
|
+
|
|
52
|
+
1. `git diff -- '*.vue'` plus changed composables to scope the change.
|
|
53
|
+
2. Read each component's `setup`/template against the priorities, reactivity first.
|
|
54
|
+
3. Trace any SSR-sensitive value from setup to template.
|
|
55
|
+
|
|
56
|
+
## Proactive Triggers
|
|
57
|
+
|
|
58
|
+
Surface these WITHOUT being asked:
|
|
59
|
+
|
|
60
|
+
- a destructured `reactive`/props in the diff → the binding that is now dead and the `toRefs` fix
|
|
61
|
+
- a `window`/`localStorage`/`Date` read in `setup` of an SSR page → the hydration mismatch it causes
|
|
62
|
+
- a `v-for` with no `:key` or a keyed index on a list that reorders → the DOM-reuse bug
|
|
63
|
+
|
|
64
|
+
## Output
|
|
65
|
+
|
|
66
|
+
```markdown
|
|
67
|
+
## Vue Review
|
|
68
|
+
|
|
69
|
+
**Scope:** {changed components / composables}
|
|
70
|
+
**Verdict:** {APPROVED / CHANGES REQUESTED}
|
|
71
|
+
|
|
72
|
+
### Critical
|
|
73
|
+
- [ ] {file}:{line} — {the reactivity/SSR trap} → {the fix}
|
|
74
|
+
|
|
75
|
+
### High
|
|
76
|
+
- [ ] {file}:{line} — {the issue} → {the fix}
|
|
77
|
+
|
|
78
|
+
### Positive
|
|
79
|
+
{what handles reactivity and SSR correctly}
|
|
80
|
+
```
|