@selesai/code 0.13.29 → 0.13.30

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 (45) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/README.md +8 -2
  3. package/dist/core/model-registry.d.ts +13 -1
  4. package/dist/core/model-registry.js +16 -0
  5. package/dist/defaults/settings.json +8 -13
  6. package/dist/extensions/capability-gateway/catalog.ts +2 -2
  7. package/dist/extensions/capability-gateway/index.ts +103 -18
  8. package/dist/extensions/capability-gateway/integration.test.ts +394 -8
  9. package/dist/extensions/capability-gateway/routing.test.ts +415 -0
  10. package/dist/extensions/capability-gateway/routing.ts +221 -0
  11. package/dist/extensions/grep-app/index.ts +10 -0
  12. package/dist/extensions/jev/decisions.test.ts +316 -0
  13. package/dist/extensions/jev/decisions.ts +527 -0
  14. package/dist/extensions/jev/test-support.ts +233 -0
  15. package/dist/extensions/jev-advisory-lifecycle.test.ts +206 -0
  16. package/dist/extensions/jev-advisory-memory.test.ts +191 -0
  17. package/dist/extensions/jev-advisory-recommendations.test.ts +240 -0
  18. package/dist/extensions/jev-advisory-routing.ts +539 -0
  19. package/dist/extensions/package.json +2 -2
  20. package/dist/extensions/pi-hermes-memory/src/memory-search-bridge.ts +40 -0
  21. package/dist/extensions/pi-hermes-memory/src/tools/memory-search-tool.ts +57 -46
  22. package/dist/extensions/pi-hermes-memory/src/tools/memory-tool.ts +17 -0
  23. package/dist/extensions/pi-hermes-memory/src/tools/session-search-tool.ts +10 -0
  24. package/dist/extensions/pi-hermes-memory/src/tools/skill-tool.ts +5 -0
  25. package/dist/extensions/pi-hermes-memory/tests/tools/memory-search-tool.test.ts +25 -0
  26. package/dist/extensions/pi-intercom/index.ts +10 -0
  27. package/dist/extensions/pi-subagents/src/extension/fanout-child.ts +5 -0
  28. package/dist/extensions/pi-subagents/src/extension/index.ts +5 -0
  29. package/dist/extensions/pi-subagents/src/intercom/native-supervisor-channel.ts +10 -0
  30. package/dist/extensions/pi-subagents/src/runs/background/wait-tool.ts +10 -0
  31. package/dist/extensions/pi-web-agent/src/extension.ts +5 -0
  32. package/dist/extensions/question/index.ts +5 -0
  33. package/dist/extensions/tokenin-onboarding.ts +185 -0
  34. package/dist/skills/code-review-and-quality/SKILL.md +396 -0
  35. package/dist/skills/code-simplification/SKILL.md +331 -0
  36. package/dist/skills/incremental-implementation/SKILL.md +249 -0
  37. package/dist/skills/planning-and-task-breakdown/SKILL.md +257 -0
  38. package/dist/skills/references/agent-skills-LICENSE +21 -0
  39. package/dist/skills/references/definition-of-done.md +67 -0
  40. package/dist/skills/references/performance-checklist.md +236 -0
  41. package/dist/skills/references/security-checklist.md +248 -0
  42. package/docs/settings.md +68 -31
  43. package/package.json +3 -3
  44. package/dist/extensions/auto-model.test.ts +0 -438
  45. package/dist/extensions/auto-model.ts +0 -357
@@ -0,0 +1,248 @@
1
+ # Security Checklist
2
+
3
+ Quick reference for web application security. Use alongside the `security-and-hardening` skill.
4
+
5
+ ## Table of Contents
6
+
7
+ - [Threat Modeling (Start Here)](#threat-modeling-start-here)
8
+ - [Pre-Commit Checks](#pre-commit-checks)
9
+ - [Authentication](#authentication)
10
+ - [Authorization](#authorization)
11
+ - [Input Validation](#input-validation)
12
+ - [Security Headers](#security-headers)
13
+ - [CORS Configuration](#cors-configuration)
14
+ - [Data Protection](#data-protection)
15
+ - [Dependency Security](#dependency-security)
16
+ - [AI / LLM Security](#ai--llm-security)
17
+ - [Error Handling](#error-handling)
18
+ - [OWASP Top 10 Quick Reference](#owasp-top-10-quick-reference)
19
+ - [OWASP Top 10 for LLMs Quick Reference](#owasp-top-10-for-llms-quick-reference)
20
+
21
+ ## Threat Modeling (Start Here)
22
+
23
+ Before reaching for controls, spend five minutes thinking like an attacker:
24
+
25
+ - [ ] Trust boundaries mapped (requests, uploads, webhooks, third-party APIs, LLM output, and local values written by processes you don't control)
26
+ - [ ] Assets named (credentials, PII, payment data, admin actions, money movement)
27
+ - [ ] STRIDE run per boundary (Spoofing, Tampering, Repudiation, Info disclosure, DoS, Elevation)
28
+ - [ ] Abuse cases written next to use cases ("how would I misuse this?")
29
+
30
+ ## Pre-Commit Checks
31
+
32
+ - [ ] No secrets in code (`git diff --cached | grep -i "password\|secret\|api_key\|token"`)
33
+ - [ ] `.gitignore` covers: `.env`, `.env.local`, `*.pem`, `*.key`
34
+ - [ ] `.env.example` uses placeholder values (not real secrets)
35
+
36
+ ## Authentication
37
+
38
+ - [ ] Passwords hashed with bcrypt (≥12 rounds), scrypt, or argon2
39
+ - [ ] Session cookies: `httpOnly`, `secure`, `sameSite: 'lax'`
40
+ - [ ] Session expiration configured (reasonable max-age)
41
+ - [ ] Rate limiting on login endpoint (≤10 attempts per 15 minutes)
42
+ - [ ] Password reset tokens: time-limited (≤1 hour), single-use
43
+ - [ ] Account lockout after repeated failures (optional, with notification)
44
+ - [ ] MFA supported for sensitive operations (optional but recommended)
45
+
46
+ ## Authorization
47
+
48
+ - [ ] Every protected endpoint checks authentication
49
+ - [ ] Every resource access checks ownership/role (prevents IDOR)
50
+ - [ ] Admin endpoints require admin role verification
51
+ - [ ] API keys scoped to minimum necessary permissions
52
+ - [ ] JWT tokens validated (signature, expiration, issuer)
53
+
54
+ ## Input Validation
55
+
56
+ - [ ] All user input validated at system boundaries (API routes, form handlers)
57
+ - [ ] Validation uses allowlists (not denylists)
58
+ - [ ] String lengths constrained (min/max)
59
+ - [ ] Numeric ranges validated
60
+ - [ ] Email, URL, and date formats validated with proper libraries
61
+ - [ ] File uploads: type restricted, size limited, content verified
62
+ - [ ] SQL queries parameterized (no string concatenation)
63
+ - [ ] HTML output encoded (use framework auto-escaping)
64
+ - [ ] URLs validated before redirect (prevent open redirect)
65
+ - [ ] Server-side URL fetches allowlisted; private/reserved IPs blocked (prevent SSRF)
66
+ - [ ] Destructive path operations (delete/move/overwrite): symlinks resolved, allowlisted root, minimum depth, ownership evidence read before the call
67
+
68
+ ### Destructive Path Operations
69
+
70
+ Containment for a target named by data. Resolve first, then decide — and treat the
71
+ result as a candidate, not as authorization:
72
+
73
+ ```typescript
74
+ import { realpath, readFile } from 'node:fs/promises';
75
+ import { resolve, relative, isAbsolute, join, sep } from 'node:path';
76
+
77
+ const ALLOWED_ROOTS = ['/var/lib/myapp/sessions']; // an allowlist, not a pattern
78
+ const MIN_DEPTH = 1; // so a root is never the target
79
+
80
+ async function resolveDeletable(candidate: string, expectedOwner: string) {
81
+ const target = await realpath(resolve(candidate)); // symlinks resolved BEFORE the check
82
+ const inRoot = ALLOWED_ROOTS.some((root) => {
83
+ const rel = relative(root, target);
84
+ // `rel === '..'` / `'../'` only — a plain `startsWith('..')` would also
85
+ // reject a legitimate child named `..cache`.
86
+ if (rel === '' || rel === '..' || rel.startsWith(`..${sep}`) || isAbsolute(rel)) return false;
87
+ return rel.split(sep).length >= MIN_DEPTH;
88
+ });
89
+ if (!inRoot) throw new Error(`refusing: outside allowed roots (${target})`);
90
+
91
+ const owner = await readFile(join(target, '.owner'), 'utf8').catch(() => null);
92
+ if (owner?.trim() !== expectedOwner) throw new Error(`refusing: unproven owner (${target})`);
93
+ return target;
94
+ }
95
+ ```
96
+
97
+ What this does not do, and must be said where the snippet is copied from:
98
+
99
+ - **The marker is self-attestation.** Anything that can write inside the root can write
100
+ `.owner`. `expectedOwner` has to come from authenticated state, and the marker needs
101
+ integrity protection (restrictive ownership, or a MAC) before it is authorization
102
+ rather than a consistency check against a misderived target.
103
+ - **Returning a path leaves a check/use race.** Where an untrusted process can swap an
104
+ ancestor between the check and the call, operate on a descriptor with no-follow,
105
+ beneath-the-root semantics, or guarantee the hierarchy is immutable for the duration.
106
+
107
+ ## Security Headers
108
+
109
+ ```
110
+ Content-Security-Policy: default-src 'self'; script-src 'self'
111
+ Strict-Transport-Security: max-age=31536000; includeSubDomains
112
+ X-Content-Type-Options: nosniff
113
+ X-Frame-Options: DENY
114
+ X-XSS-Protection: 0 (disabled, rely on CSP)
115
+ Referrer-Policy: strict-origin-when-cross-origin
116
+ Permissions-Policy: camera=(), microphone=(), geolocation=()
117
+ ```
118
+
119
+ ## CORS Configuration
120
+
121
+ ```typescript
122
+ // Restrictive (recommended)
123
+ cors({
124
+ origin: ['https://yourdomain.com', 'https://app.yourdomain.com'],
125
+ credentials: true,
126
+ methods: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE'],
127
+ allowedHeaders: ['Content-Type', 'Authorization'],
128
+ })
129
+
130
+ // NEVER use in production:
131
+ cors({ origin: '*' }) // Allows any origin
132
+ ```
133
+
134
+ ## Data Protection
135
+
136
+ - [ ] Sensitive fields excluded from API responses (`passwordHash`, `resetToken`, etc.)
137
+ - [ ] Sensitive data not logged (passwords, tokens, full CC numbers)
138
+ - [ ] PII encrypted at rest (if required by regulation)
139
+ - [ ] HTTPS for all external communication
140
+ - [ ] Database backups encrypted
141
+ - [ ] Personal data is classified, collected against a stated purpose, and minimized
142
+ - [ ] Personal data has a retention limit and a working deletion path (incl. backups, caches, indexes)
143
+ - [ ] Export/delete (data-subject) requests are supported where required; third-party sharing has consent and a data-processing agreement
144
+
145
+ ## Dependency Security
146
+
147
+ First locate the **installation boundary**. If the package is matched by a parent `workspaces` declaration, use that workspace root; otherwise use the nearest project root that owns both its manifest and dependency graph. At that boundary, corroborate `packageManager` (when present), the lockfile, and CI commands. Stop if they disagree or competing manager lockfiles exist there. A nested project is independent only when it is outside the parent workspace; independent subprojects may legitimately use different managers.
148
+
149
+ | Manager/version signal | Frozen/immutable CI install | Known-advisory audit |
150
+ |---|---|---|
151
+ | npm (`package-lock.json` or `npm-shrinkwrap.json`) | `npm ci` | `npm audit` |
152
+ | pnpm | `pnpm install --frozen-lockfile` | `pnpm audit` |
153
+ | Yarn 2+ | `yarn install --immutable` | `yarn npm audit -A -R` |
154
+ | Yarn 1 | `yarn install --frozen-lockfile` | `yarn audit` |
155
+
156
+ For an unlisted manager or version, consult its official documentation; do not substitute another manager's commands or newer defaults.
157
+
158
+ ### Install-Script Gate
159
+
160
+ Never discover dependency lifecycle scripts by first executing an ordinary install on a client whose defaults have not been verified.
161
+
162
+ 1. Bootstrap with dependency scripts disabled, or with a documented default-deny policy plus fail-closed enforcement.
163
+ 2. Inspect the exact script source and package version before approval.
164
+ 3. Record the narrowest native allow/deny policy at the installation boundary and commit it.
165
+ 4. Run a clean frozen/immutable install with that policy and verify the required packages still build.
166
+
167
+ **Point-in-time snapshot:** Package-manager defaults and command names change quickly. Verify this matrix against the pinned client's current official documentation before relying on it.
168
+
169
+ | Manager version | Native policy |
170
+ |---|---|
171
+ | npm without verified granular approvals | Bootstrap with `npm ci --ignore-scripts`, or persist `ignore-scripts=true` when project-wide blocking is intended. Keep scripts disabled or deliberately upgrade before allowing any reviewed dependency script. |
172
+ | npm 11.18.x (verified on 11.18.0) | Unreviewed dependency scripts run with a warning by default. Enforce `strict-allow-scripts=true` before a normal install, then use the workspace-unaware `npm install-scripts ls` from the installation boundary; keep approvals version-pinned and denials name-wide. |
173
+ | npm 12.x (verified on 12.0.1) | Unreviewed dependency scripts are skipped by default; `strict-allow-scripts=true` makes their presence fail the install before execution. Use the same `npm install-scripts` review and approval flow. |
174
+ | pnpm 11+ | Use `pnpm approve-builds` and commit `allowBuilds` decisions; `strictDepBuilds` defaults to `true`, so unreviewed builds fail. |
175
+ | pnpm 10.26–10.x | Configure `allowBuilds` explicitly, or use `pnpm approve-builds` with the legacy `onlyBuiltDependencies` / `ignoredBuiltDependencies` lists. Set `strictDepBuilds: true`; its v10 default is `false`. |
176
+ | pnpm 10.1–10.25 | `pnpm approve-builds` records the legacy lists; enable `strictDepBuilds` where supported (10.3+). |
177
+ | Older or unknown pnpm | Bootstrap with `pnpm install --frozen-lockfile --ignore-scripts`. Keep scripts disabled unless the pinned version documents an enforceable policy. |
178
+ | Yarn 4.14+ | Dependency postinstalls are disabled by default. Grant only required exceptions with top-level `dependenciesMeta.<package>.built: true`. |
179
+ | Yarn 2–4.13 | Set `enableScripts: false` in `.yarnrc.yml`, then grant only required exceptions with top-level `dependenciesMeta.<package>.built: true`; do not enable scripts globally. |
180
+ | Yarn 1 | Bootstrap with `yarn install --ignore-scripts`; keep scripts disabled unless each required exception is reviewed under the pinned client's documented workflow. |
181
+
182
+ Authoritative checks: [npm install-scripts](https://docs.npmjs.com/cli/v11/commands/npm-install-scripts/), [install policy](https://docs.npmjs.com/cli/v11/commands/npm-install/), and [CLI releases](https://github.com/npm/cli/releases); [pnpm approve-builds](https://pnpm.io/cli/approve-builds) and [build settings](https://pnpm.io/settings#allowbuilds); [Yarn security](https://yarnpkg.com/features/security) and [manifest](https://yarnpkg.com/configuration/manifest#dependenciesMeta).
183
+
184
+ **Supply-chain hygiene** (advisory audits do not catch newly malicious packages):
185
+ - [ ] Exactly one authoritative lockfile per project/workspace root is committed and CI never rewrites it
186
+ - [ ] Critical/high findings are triaged for reachability; deferrals have a reason and review date
187
+ - [ ] Forced audit remediation (`npm audit fix --force` or equivalent) is never automatic; remediation diffs and changelogs are reviewed
188
+ - [ ] Registry signatures/provenance are verified where the manager supports it
189
+ - [ ] Dependency lifecycle scripts are blocked before first execution and approved only through the pinned manager's native policy
190
+ - [ ] New dependencies are reviewed for ownership, maintenance, release age, provenance, transitive graph, and typosquatting
191
+
192
+ ## AI / LLM Security
193
+
194
+ For any feature that calls an LLM (chatbots, summarizers, agents, RAG):
195
+
196
+ - [ ] Model output treated as untrusted — never into `eval`/SQL/shell/`innerHTML`/file paths
197
+ - [ ] Prompt injection assumed; permissions enforced in code, not in the system prompt
198
+ - [ ] Secrets, cross-tenant data, and full system prompts kept out of the context window
199
+ - [ ] Tool/agent permissions scoped; destructive or irreversible actions require confirmation
200
+ - [ ] Token, rate, and recursion/loop limits set (bound consumption)
201
+
202
+ ## Error Handling
203
+
204
+ ```typescript
205
+ // Production: generic error, no internals
206
+ res.status(500).json({
207
+ error: { code: 'INTERNAL_ERROR', message: 'Something went wrong' }
208
+ });
209
+
210
+ // NEVER in production:
211
+ res.status(500).json({
212
+ error: err.message,
213
+ stack: err.stack, // Exposes internals
214
+ query: err.sql, // Exposes database details
215
+ });
216
+ ```
217
+
218
+ ## OWASP Top 10 Quick Reference
219
+
220
+ | # | Vulnerability | Prevention |
221
+ |---|---|---|
222
+ | 1 | Broken Access Control | Auth checks on every endpoint, ownership verification |
223
+ | 2 | Cryptographic Failures | HTTPS, strong hashing, no secrets in code |
224
+ | 3 | Injection | Parameterized queries, input validation |
225
+ | 4 | Insecure Design | Threat modeling, spec-driven development |
226
+ | 5 | Security Misconfiguration | Security headers, minimal permissions, audit deps |
227
+ | 6 | Vulnerable Components | The ecosystem's dependency audit (`npm audit`, `pip-audit`, ...), keep deps updated, minimal deps |
228
+ | 7 | Auth Failures | Strong passwords, rate limiting, session management |
229
+ | 8 | Data Integrity Failures | Verify updates/dependencies, signed artifacts |
230
+ | 9 | Logging Failures | Log security events, don't log secrets |
231
+ | 10 | SSRF | Validate/allowlist URLs, restrict outbound requests |
232
+
233
+ ## OWASP Top 10 for LLMs Quick Reference
234
+
235
+ For apps with LLM features. See the [OWASP GenAI Security Project](https://genai.owasp.org/llm-top-10/).
236
+
237
+ | ID | Risk | Prevention |
238
+ |---|---|---|
239
+ | LLM01 | Prompt Injection | Don't trust the system prompt as a boundary; enforce permissions in code |
240
+ | LLM02 | Sensitive Information Disclosure | Keep secrets/PII out of prompts; filter outputs |
241
+ | LLM03 | Supply Chain | Vet models, datasets, and plugins like any dependency |
242
+ | LLM04 | Data and Model Poisoning | Use trusted model sources, verify integrity; vet fine-tuning and RAG data |
243
+ | LLM05 | Improper Output Handling | Treat model output as untrusted; validate, parameterize, encode |
244
+ | LLM06 | Excessive Agency | Scope tool permissions; confirm destructive actions |
245
+ | LLM07 | System Prompt Leakage | Assume the system prompt can leak; put no secrets in it |
246
+ | LLM08 | Vector and Embedding Weaknesses | Partition RAG embeddings per tenant; validate documents before indexing |
247
+ | LLM09 | Misinformation | Ground answers with citations; validate critical claims; keep a human in the loop |
248
+ | LLM10 | Unbounded Consumption | Cap tokens, request rate, and loop/recursion depth |
package/docs/settings.md CHANGED
@@ -46,49 +46,86 @@ Use `/trust` in interactive mode to save a project trust decision for future ses
46
46
  }
47
47
  ```
48
48
 
49
- ### Automatic Model Routing
49
+ ### Jev Advisory Routing
50
50
 
51
- The bundled `auto-model` extension can classify each idle, top-level prompt as `simple`, `medium`,
52
- `complex`, or `reasoning` and switch to the model configured for that tier before the turn starts.
53
- Classification uses the Jev decisions model through the Token-In gateway. Routing stays off until
54
- `autoModel.enabled` is `true`.
51
+ The bundled `jev-advisory-routing` extension uses the Jev decisions model for bounded opt-in
52
+ routing. Every route stays off until it is enabled in `jevAdvisory`; the two routes share one
53
+ Jev provider/model pair:
54
+
55
+ - `memory` — only after an explicit durable-memory cue (for example “the convention we
56
+ decided” or “don't repeat the past failure”), Jev chooses one read-only local
57
+ `memory_search` target. Jev never sees memory contents, and no memory is written.
58
+ - `recommendations` — one discovered skill or prompt workflow that fits, or a proportionate
59
+ verification level. Nothing is loaded, started, or executed: the recommendation is context for the
60
+ agent, and required project/workflow gates are unchanged.
55
61
 
56
62
  | Setting | Type | Default | Description |
57
63
  |---------|------|---------|-------------|
58
- | `autoModel.enabled` | boolean | `false` | Enable automatic per-prompt routing |
59
- | `autoModel.classifier.provider` | string | `"tokenin"` | Provider serving the Jev decisions deployment |
60
- | `autoModel.classifier.model` | string | `"jev-1.13"` | Decisions model the classifier calls |
61
- | `autoModel.classifier.baseUrl` | string | inherited | Base URL override; defaults to any registered model of `classifier.provider` |
62
- | `autoModel.classifier.timeoutMs` | number | `10000` | Classifier request timeout (ms) |
63
- | `autoModel.classifier.minConfidence` | number | `0.5` | Below this Jev confidence the fallback tier is used |
64
- | `autoModel.classifier.contextTurns` | number | `4` | Prior user turns sent as classifier context |
65
- | `autoModel.classifier.contextChars` | number | `4000` | Character budget for that context |
66
- | `autoModel.tiers.simple` | string | `"tokenin/deepseek-v4.1-flash"` | Model for greetings, lookups, and tiny transformations |
67
- | `autoModel.tiers.medium` | string | `"tokenin/celestial-pro"` | Model for routine coding, edits, and explanations (the default fallback) |
68
- | `autoModel.tiers.complex` | string | `"tokenin/celestial-max"` | Model for non-trivial engineering and root-cause debugging |
69
- | `autoModel.tiers.reasoning` | string | `"tokenin/celestial-ultra"` | Model for open-ended reasoning and tradeoffs |
70
- | `autoModel.fallbackTier` | string | `"medium"` | Tier used when the classifier is unavailable |
71
-
72
- Each tier value is `provider/modelId`, with an optional `:thinkingLevel` suffix (for example
73
- `tokenin/celestial-max:max`). Only idle, top-level prompts are routed: queued steering/follow-up
74
- messages, extension-injected messages, and slash commands are left alone, because the session model
75
- is global. Selecting a model with `/model` suspends routing for the rest of the session.
64
+ | `jevAdvisory.provider` | string | `"tokenin"` | Provider serving the Jev decisions deployment |
65
+ | `jevAdvisory.model` | string | `"jev-1.13"` | Decisions model every route calls |
66
+ | `jevAdvisory.baseUrl` | string | inherited | Base URL override; defaults to any registered model of `provider` |
67
+ | `jevAdvisory.routes.memory.enabled` | boolean | `false` | Enable the memory-lookup route |
68
+ | `jevAdvisory.routes.recommendations.enabled` | boolean | `false` | Enable skill/workflow and verification recommendations |
69
+ | `<route>.timeoutMs` | number | `8000` | Route request timeout (ms); memory is capped at 750ms |
70
+ | `<route>.minConfidence` | number | `0.6` | Below this Jev confidence the route abstains |
71
+ | `<route>.contextTurns` | number | `4` | Prior user turns sent as recommendation context; memory sends only the current bounded prompt |
72
+ | `<route>.contextChars` | number | `4000` | Character budget for recommendation context |
73
+ | `<route>.payloadBytes` | number | `8192` | Hard cap on the serialized decision request |
74
+
75
+ Only idle, top-level, interactive prompts are routed: queued steering/follow-up input, slash
76
+ commands, and extension-injected turns are skipped, and each turn is routed at most once. The memory
77
+ route sends no history to Jev; on an accepted target it runs one local, read-only lookup (at most five
78
+ results, bounded before injection). A missing Token-In subscription, a timeout, a malformed or
79
+ low-confidence answer, an unknown candidate, unavailable/empty local memory, or an oversized payload
80
+ is an ordinary abstention that leaves the existing memory policy and verification requirements in force.
76
81
 
77
82
  ```json
78
83
  {
79
- "autoModel": {
80
- "enabled": true,
81
- "classifier": { "provider": "tokenin", "model": "jev-1.13" },
82
- "tiers": {
83
- "simple": "tokenin/deepseek-v4.1-flash",
84
- "medium": "tokenin/celestial-pro",
85
- "complex": "tokenin/celestial-max",
86
- "reasoning": "tokenin/celestial-ultra"
84
+ "jevAdvisory": {
85
+ "provider": "tokenin",
86
+ "model": "jev-1.13",
87
+ "routes": {
88
+ "memory": { "enabled": true },
89
+ "recommendations": { "enabled": true }
87
90
  }
88
91
  }
89
92
  }
90
93
  ```
91
94
 
95
+ ### Capability Gateway (experimental)
96
+
97
+ The bundled `capability-gateway` extension keeps optional extension tools dormant until they are
98
+ needed: a compact `capability_catalog` lists them, `capability_discover` activates one for the
99
+ current run, and `capability_skill_show` loads one skill's full instructions. Set
100
+ `SELESAI_CAPABILITY_GATEWAY=0` to disable the gateway and keep every tool visible.
101
+
102
+ Routing has two rungs:
103
+
104
+ 1. A deterministic router activates a tool when the prompt uniquely matches its name, alias, or
105
+ discovery summary. Skills are never auto-loaded or auto-selected.
106
+ 2. Opt-in Jev tie-breaking: when the deterministic router returns an ambiguous lexical hint among
107
+ optional tools, the Jev decisions model is asked which of two or three hinted tools (or `none`)
108
+ should be exposed. Jev sees only the bounded current prompt and each hinted tool's compact
109
+ discovery line — never conversation history, tool schemas, or the full catalog. A prompt with no
110
+ lexical signal, a unique activation, and a skill-only match never reach Jev.
111
+
112
+ | Setting | Type | Default | Description |
113
+ |---------|------|---------|-------------|
114
+ | `capabilityGateway.routing.jev.enabled` | boolean | `false` | Enable Jev tie-breaking for ambiguous tool hints |
115
+ | `capabilityGateway.routing.jev.provider` | string | `"tokenin"` | Provider serving the Jev decisions deployment |
116
+ | `capabilityGateway.routing.jev.model` | string | `"jev-1.13"` | Decisions model the tie-breaker calls |
117
+ | `capabilityGateway.routing.jev.baseUrl` | string | inherited | Base URL override; defaults to any registered model of `provider` |
118
+ | `capabilityGateway.routing.jev.timeoutMs` | number | `1000` | Pre-turn request timeout (ms); hard-capped at `2000` |
119
+ | `capabilityGateway.routing.jev.minConfidence` | number | `0.6` | Below this Jev confidence the tie-breaker abstains |
120
+ | `capabilityGateway.routing.jev.payloadBytes` | number | `8192` | Hard cap on the serialized decision request |
121
+
122
+ This area is independent of `jevAdvisory`: gateway routing reads only
123
+ `capabilityGateway.routing.jev` and shares just the Jev provider/model deployment identity. A
124
+ failure, timeout, invalid answer, low confidence, or `none` is an ordinary abstention that leaves
125
+ the deterministic behavior in place. Temporary activations reset when the run settles, and
126
+ content-free telemetry on the `capability-gateway` event channel records the route outcome and
127
+ whether an activated tool was actually invoked.
128
+
92
129
  ### UI & Display
93
130
 
94
131
  | Setting | Type | Default | Description |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@selesai/code",
3
- "version": "0.13.29",
3
+ "version": "0.13.30",
4
4
  "description": "Maintained, extension-first Pi coding agent with built-in workflows, subagents, web research, questions, skills, and an enhanced terminal UI.",
5
5
  "type": "module",
6
6
  "engines": {
@@ -55,8 +55,8 @@
55
55
  "clean": "shx rm -rf dist",
56
56
  "dev": "tsx src/cli.ts",
57
57
  "dev:print": "tsx src/cli.ts --print",
58
- "test": "vitest run src/extensions/undo.test.ts src/extensions/auto-model.test.ts src/extensions/tps.test.ts src/extensions/pi-graft src/extensions/agent-browser.test.ts src/extensions/auto-session-name.test.ts src/extensions/context-compaction-reminder.test.ts src/extensions/copy-turn.test.ts src/extensions/grep-app/index.test.ts src/extensions/inline-skills.test.ts src/extensions/rtk.test.ts src/extensions/handoff-new.test.ts src/extensions/question/tests src/extensions/ponytail/test src/__tests__/tokenin-search.test.ts src/__tests__/tokenin-onboarding.test.ts src/__tests__/model-registry-defaults.test.ts src/core/system-prompt.test.ts src/core/session-format.test.ts test/settings-manager-compaction.test.ts test/suite/agent-session-runtime.test.ts test/suite/agent-session-prompt.test.ts test/suite/agent-session-queue.test.ts test/suite/agent-session-retry-events.test.ts test/suite/agent-session-compaction.test.ts test/suite/agent-session-compaction-model-overrides.test.ts test/suite/agent-session-bash-persistence.test.ts test/suite/agent-session-model-extension.test.ts test/clipboard.test.ts test/clipboard-command.test.ts test/clipboard-image.test.ts test/clipboard-image-bmp-conversion.test.ts test/clipboard-image-native-errors.test.ts src/cli/args.test.ts",
59
- "test:coverage": "vitest run --coverage src/extensions/undo.test.ts src/extensions/auto-model.test.ts src/extensions/tps.test.ts src/extensions/agent-browser.test.ts src/extensions/auto-session-name.test.ts src/extensions/context-compaction-reminder.test.ts src/extensions/copy-turn.test.ts src/extensions/grep-app/index.test.ts src/extensions/inline-skills.test.ts src/extensions/rtk.test.ts src/extensions/handoff-new.test.ts src/extensions/question/tests src/extensions/ponytail/test src/__tests__/tokenin-search.test.ts src/__tests__/tokenin-onboarding.test.ts src/__tests__/model-registry-defaults.test.ts src/core/system-prompt.test.ts src/core/session-format.test.ts test/settings-manager-compaction.test.ts test/suite/agent-session-runtime.test.ts test/suite/agent-session-prompt.test.ts test/suite/agent-session-queue.test.ts test/suite/agent-session-retry-events.test.ts test/suite/agent-session-compaction.test.ts test/suite/agent-session-compaction-model-overrides.test.ts test/suite/agent-session-bash-persistence.test.ts test/suite/agent-session-model-extension.test.ts test/clipboard.test.ts test/clipboard-command.test.ts test/clipboard-image.test.ts test/clipboard-image-bmp-conversion.test.ts test/clipboard-image-native-errors.test.ts src/cli/args.test.ts",
58
+ "test": "vitest run src/__tests__/model-registry-completion.test.ts src/extensions/jev/decisions.test.ts src/extensions/capability-gateway/routing.test.ts src/extensions/jev-advisory-memory.test.ts src/extensions/jev-advisory-recommendations.test.ts src/extensions/jev-advisory-lifecycle.test.ts src/extensions/undo.test.ts src/extensions/tps.test.ts src/extensions/pi-graft src/extensions/agent-browser.test.ts src/extensions/auto-session-name.test.ts src/extensions/context-compaction-reminder.test.ts src/extensions/copy-turn.test.ts src/extensions/grep-app/index.test.ts src/extensions/inline-skills.test.ts src/extensions/rtk.test.ts src/extensions/handoff-new.test.ts src/extensions/question/tests src/extensions/ponytail/test src/__tests__/tokenin-search.test.ts src/__tests__/tokenin-onboarding.test.ts src/__tests__/model-registry-defaults.test.ts src/core/system-prompt.test.ts src/core/session-format.test.ts test/settings-manager-compaction.test.ts test/suite/agent-session-runtime.test.ts test/suite/agent-session-prompt.test.ts test/suite/agent-session-queue.test.ts test/suite/agent-session-retry-events.test.ts test/suite/agent-session-compaction.test.ts test/suite/agent-session-compaction-model-overrides.test.ts test/suite/agent-session-bash-persistence.test.ts test/suite/agent-session-model-extension.test.ts test/clipboard.test.ts test/clipboard-command.test.ts test/clipboard-image.test.ts test/clipboard-image-bmp-conversion.test.ts test/clipboard-image-native-errors.test.ts src/cli/args.test.ts",
59
+ "test:coverage": "vitest run --coverage src/__tests__/model-registry-completion.test.ts src/extensions/jev/decisions.test.ts src/extensions/capability-gateway/routing.test.ts src/extensions/jev-advisory-memory.test.ts src/extensions/jev-advisory-recommendations.test.ts src/extensions/jev-advisory-lifecycle.test.ts src/extensions/undo.test.ts src/extensions/tps.test.ts src/extensions/agent-browser.test.ts src/extensions/auto-session-name.test.ts src/extensions/context-compaction-reminder.test.ts src/extensions/copy-turn.test.ts src/extensions/grep-app/index.test.ts src/extensions/inline-skills.test.ts src/extensions/rtk.test.ts src/extensions/handoff-new.test.ts src/extensions/question/tests src/extensions/ponytail/test src/__tests__/tokenin-search.test.ts src/__tests__/tokenin-onboarding.test.ts src/__tests__/model-registry-defaults.test.ts src/core/system-prompt.test.ts src/core/session-format.test.ts test/settings-manager-compaction.test.ts test/suite/agent-session-runtime.test.ts test/suite/agent-session-prompt.test.ts test/suite/agent-session-queue.test.ts test/suite/agent-session-retry-events.test.ts test/suite/agent-session-compaction.test.ts test/suite/agent-session-compaction-model-overrides.test.ts test/suite/agent-session-bash-persistence.test.ts test/suite/agent-session-model-extension.test.ts test/clipboard.test.ts test/clipboard-command.test.ts test/clipboard-image.test.ts test/clipboard-image-bmp-conversion.test.ts test/clipboard-image-native-errors.test.ts src/cli/args.test.ts",
60
60
  "prepare": "npm run build",
61
61
  "build": "npm run clean && tsgo -p tsconfig.build.json && shx chmod +x dist/cli.js dist/rpc-entry.js && npm run copy-assets",
62
62
  "copy-assets": "shx mkdir -p dist/modes/interactive/theme && shx cp src/modes/interactive/theme/*.json dist/modes/interactive/theme/ && shx mkdir -p dist/modes/interactive/assets && shx cp src/modes/interactive/assets/*.png dist/modes/interactive/assets/ && shx mkdir -p dist/core/export-html/vendor && shx cp src/core/export-html/template.html src/core/export-html/template.css src/core/export-html/template.js dist/core/export-html/ && shx cp src/core/export-html/vendor/*.js dist/core/export-html/vendor/ && shx mkdir -p dist/defaults && shx cp src/defaults/* dist/defaults/ && shx mkdir -p dist/extensions && node scripts/copy-extensions.mjs && shx mkdir -p dist/themes && shx cp -r src/themes/. dist/themes/ && shx mkdir -p dist/skills && shx cp -r src/skills/. dist/skills/"