@notis_ai/cli 0.2.0-beta.186.1 → 0.2.0-beta.187.1

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.
@@ -2,8 +2,8 @@
2
2
  name: notis-cli
3
3
  description: Use when agents should work through the Notis CLI, especially to develop Notis apps locally or to access Notis, Composio, or MCP tools they do not currently have loaded directly.
4
4
  mcp_resource: true
5
- mcp_tool_patterns: []
6
- mcp_references: ["references/app-delivery.md", "references/tool-examples.md", "references/native-databases.md", "references/troubleshooting.md"]
5
+ mcp_tool_patterns: ["LOCAL_NOTIS_GET_INTELLIGENCE_POLICY"]
6
+ mcp_references: ["references/app-delivery.md", "references/tool-examples.md", "references/native-databases.md", "references/troubleshooting.md", "references/intelligence.md"]
7
7
  ---
8
8
 
9
9
  # Notis CLI Skill
@@ -137,3 +137,18 @@ also rewrites these links to their published URIs.
137
137
  - [Toolkit mental model](references/tool-examples.md)
138
138
  - [Native database access](references/native-databases.md)
139
139
  - [Supporting commands](references/troubleshooting.md)
140
+
141
+ ## Intelligence for skills and delegated work
142
+
143
+ Skills request `low`, `medium`, or `high`, never a fixed model name. Discover the
144
+ read-only `LOCAL_NOTIS_GET_INTELLIGENCE_POLICY` tool to obtain the shared `contract`
145
+ and current mapping
146
+ for `notis`, `codex`, or `claude_code` and the requested `level`. Resolve model and
147
+ reasoning effort together at the start of each job; validate the selected options
148
+ with the executing harness. Explicit invocation overrides win. A fixed-model
149
+ harness may inherit and disclose that the level was not applied; an automated
150
+ launcher needing an exact selection stops before side effects if policy is unavailable.
151
+ Repository and installed skills consume that same response; neither needs a
152
+ checkout-relative document. Record actual execution receipts, not the level name, as model provenance. Media
153
+ engines remain separate capabilities selected by their tools. See
154
+ [the intelligence contract](references/intelligence.md) for cross-environment details.
@@ -0,0 +1,94 @@
1
+ # Agent intelligence levels
2
+
3
+ This is one shared contract for repository skills and account-installed skills.
4
+ Read it from the `contract` field returned by `LOCAL_NOTIS_GET_INTELLIGENCE_POLICY`,
5
+ directly as a native tool or through the authenticated Notis CLI. The same response
6
+ contains current harness mappings and a `contract_revision` fingerprint. No local
7
+ repository document is a runtime prerequisite. This bundled guide is the source
8
+ served by that lookup, not a separate environment-specific contract.
9
+
10
+ Skills request **low**, **medium**, or **high**. They never maintain model names,
11
+ version pins, family aliases, effort tables, or price scorecards. The current
12
+ Notis runtime policy is the source of truth, on every operating system and host.
13
+
14
+ ## Choosing a level
15
+
16
+ | Level | Work |
17
+ | --- | --- |
18
+ | **low** | Bounded extraction, classification against a supplied rubric, formatting, and repetitive generation from complete inputs. |
19
+ | **medium** | Synthesis, writing and reviewing prose from supplied evidence, and moderately complex bounded work. |
20
+ | **high** | The skill default when unspecified: complex reasoning, investigation, coding, code review, and orchestration. |
21
+
22
+ These are skill defaults, not changes to account or product defaults. The user's
23
+ explicit instruction for this invocation wins: level, exact model, effort,
24
+ harness, or inheritance from the current session. Preserve the scope of that
25
+ override; never save a lasting preference unless asked. Maximum-depth requests
26
+ are invocation overrides, not a fourth Notis level.
27
+
28
+ ## Resolve at execution time
29
+
30
+ Discover **get current Notis intelligence policy for each harness** through the
31
+ Notis tool catalogue. The read-only tool is `LOCAL_NOTIS_GET_INTELLIGENCE_POLICY`:
32
+
33
+ ```bash
34
+ npx --package @notis_ai/cli@latest -- notis tools exec LOCAL_NOTIS_GET_INTELLIGENCE_POLICY \
35
+ --arguments '{"harness":"codex","level":"low"}'
36
+ ```
37
+
38
+ Omit arguments to read all levels. Harness keys are `notis`, `codex`, and
39
+ `claude_code`. A local Mac, Windows host, cloud sandbox, or CI runner uses the
40
+ same contract. Cursor or another host must identify its actual execution engine;
41
+ it must not pretend to be a supported harness based on installed binaries.
42
+
43
+ The projection is generated from the backend native intelligence configuration and external-harness policy. It contains no
44
+ second mapping. Weekly policy changes therefore require no skill edits.
45
+
46
+ - Resolve **both model and reasoning effort**. Level names are not effort names.
47
+ - Resolve once per delegated job; keep its `policy_revision` and selection stable
48
+ through claim, generation, retry and completion. A new job gets a fresh policy.
49
+ - Explicit user choices override the selection; validate them with the executing
50
+ harness. Never substitute another model, buy API capacity, or change accounts
51
+ because a selection is unavailable.
52
+ - Validate the request against advertised harness capabilities. Policy is not
53
+ evidence of entitlement, quota, installed support or successful execution.
54
+ - Use native `intelligence_mode` when the Notis delegation interface supports it.
55
+ External launchers translate the returned selection into their supported options.
56
+ - Do not downgrade or restart the main session to enforce a skill default.
57
+ - A single-model harness can inherit its current configuration and disclose that
58
+ the requested level was not applied. Unknown or unavailable mappings are not
59
+ permission to guess a model. Automated launchers that require an exact selection
60
+ stop before claiming jobs or producing side effects and explain the missing policy.
61
+ - Before this lookup is deployed, use a current runtime-injected policy if present;
62
+ otherwise use the transparent inheritance behavior above. Do not copy a temporary
63
+ model table into skills as a rollout workaround.
64
+
65
+ ## Modalities, product assertions and provenance
66
+
67
+ Image, speech, video, embedding and provider-research engines are capabilities,
68
+ not interchangeable text-reasoning levels. Skills discover the current native
69
+ capability and let its backend select the engine. External scripts requiring an
70
+ exact provider-specific identifier must resolve current supported configuration
71
+ or take an explicit invocation override; they must not pass `low` as an engine ID.
72
+
73
+ Test specs assert behavior against the current backend configuration, rather than
74
+ freezing last month's model names. Preserve exact comparisons: derive the expected
75
+ identifier from the owning policy or tool configuration, then compare the receipt.
76
+ Do not weaken a routing test to merely check that some model name exists.
77
+
78
+ Persist **the actual model that ran**, not an intelligence level. Resolve before
79
+ claiming jobs when the identifier participates in a prompt hash or lease contract.
80
+ Verify execution readback before certifying provenance; aliases and requested
81
+ settings are not actual-model receipts. Preserve historical evidence and existing
82
+ records. Do not rewrite an old receipt as today's policy.
83
+
84
+ ## Subscription execution
85
+
86
+ A level chooses intelligence, not payment authority. Use the current harness's
87
+ sub-agents or the user's subscription CLI. The existing direct-provider approval
88
+ boundary remains in the workspace/account provider-approval policy.
89
+
90
+ For subscription CLI subprocesses, remove provider API-key/base-URL variables
91
+ from the child environment. Preserve native subscription credentials; never log
92
+ out or rewrite account authentication to enforce a level. Check the harness's
93
+ execution/authentication readback. Resolve only once per job, batch bounded items
94
+ where appropriate, and keep existing concurrency and usage limits.
@@ -43,9 +43,8 @@ export interface UseHandoverResult {
43
43
  * feedback button should let the user write in their own words.
44
44
  *
45
45
  * Pass `skill` to bind the work to a skill declared in `notis.config.ts`; the
46
- * host rejects a key the app does not declare. `autoSend` is accepted for
47
- * forward compatibility; today's hosts always return `drafted` and let the
48
- * user press send.
46
+ * host rejects a key the app does not declare. `autoSend` submits the prepared
47
+ * message on an active user gesture; background calls still open a draft.
49
48
  */
50
49
  export function useHandover(): UseHandoverResult {
51
50
  const runtime = useNotisRuntime();
@@ -10,6 +10,7 @@ import React, {
10
10
  useState,
11
11
  type ReactNode,
12
12
  } from 'react';
13
+ import { isInteractionElementVisible } from './visibility';
13
14
 
14
15
  export type ShortcutScope = 'app' | 'route' | 'collection' | 'detail' | 'modal';
15
16
 
@@ -215,6 +216,25 @@ function consumeShortcut(event: KeyboardEvent, definition: ShortcutDefinition):
215
216
  void definition.onTrigger(event);
216
217
  }
217
218
 
219
+ // Apps built before collections stopped binding Escape to an empty selection
220
+ // still register it, which swallows Escape for nothing. With collection items
221
+ // rendered and none selected, leave Escape to the enclosing surface (the Portal
222
+ // closes its frontmost layer, then returns to Inbox).
223
+ function isEmptyCollectionClear(shortcut: ShortcutDefinition, ownerDocument: Document, event: KeyboardEvent): boolean {
224
+ if (event.key !== 'Escape' || shortcut.id !== 'collection.clear') return false;
225
+ const items = collectionItems(ownerDocument).filter((item) => isInteractionElementVisible(item as HTMLElement));
226
+ return items.length > 0 && !items.some((item) => item.getAttribute('aria-selected') === 'true');
227
+ }
228
+
229
+ /** App views render in open shadow roots, which document queries do not enter. */
230
+ function collectionItems(root: Document | ShadowRoot): Element[] {
231
+ const items = Array.from(root.querySelectorAll('[data-notis-collection-item-id], [data-notis-row-id]'));
232
+ for (const element of Array.from(root.querySelectorAll('*'))) {
233
+ if (element.shadowRoot) items.push(...collectionItems(element.shadowRoot));
234
+ }
235
+ return items;
236
+ }
237
+
218
238
  // Native dialogs make the background inert, but document capture listeners still
219
239
  // receive their keyboard events. Leave those events to the dialog and its controls.
220
240
  function isDialogEvent(event: KeyboardEvent): boolean {
@@ -293,7 +313,8 @@ function registerFallbackShortcut(input: Omit<ShortcutRegistration, 'id' | 'orde
293
313
  const token = chordToken(eventChord(event));
294
314
  for (const registration of applicableRegistrations(registrations.values())) {
295
315
  for (const shortcut of registration.getShortcuts()) {
296
- if (shortcut.enabled === false || (editable && !shortcut.allowInEditable) || (event.repeat && !shortcut.allowRepeat)) continue;
316
+ if (shortcut.enabled === false || (editable && !shortcut.allowInEditable) || (event.repeat && !shortcut.allowRepeat)
317
+ || isEmptyCollectionClear(shortcut, ownerDocument, event)) continue;
297
318
  const match = parseShortcut(shortcut).some(
298
319
  (candidate) => candidate.sequence.length === 1 && chordToken(candidate.sequence[0]!) === token,
299
320
  );
@@ -407,6 +428,7 @@ function ShortcutProviderRoot({ children }: { children: ReactNode }) {
407
428
  .filter((shortcut) => shortcut.enabled !== false)
408
429
  .filter((shortcut) => !editable || shortcut.allowInEditable)
409
430
  .filter((shortcut) => !event.repeat || shortcut.allowRepeat)
431
+ .filter((shortcut) => !isEmptyCollectionClear(shortcut, document, event))
410
432
  .flatMap(parseShortcut);
411
433
  if (candidates.length === 0) continue;
412
434
 
@@ -310,9 +310,8 @@ export interface HandoverPayload {
310
310
  */
311
311
  skill?: string;
312
312
  /**
313
- * Accepted for forward compatibility. The portal never submits a composer on
314
- * the user's behalf today, so every handover resolves `drafted`; `sent` is
315
- * reserved for a host that can genuinely dispatch the run.
313
+ * Submit on an active user gesture when the host supports immediate handover;
314
+ * background calls still open an editable draft.
316
315
  */
317
316
  autoSend?: boolean;
318
317
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@notis_ai/cli",
3
- "version": "0.2.0-beta.186.1",
3
+ "version": "0.2.0-beta.187.1",
4
4
  "description": "Agent-first Notis CLI for apps and generic tool execution",
5
5
  "type": "module",
6
6
  "bin": {