agent-nuvira 3.5.6 → 3.5.7

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 (110) hide show
  1. package/.agents/skills/index.json +16 -0
  2. package/.agents/skills/motion/SKILL.md +27 -0
  3. package/README.md +56 -1
  4. package/dist/cli/chat.d.ts +76 -17
  5. package/dist/cli/chat.d.ts.map +1 -1
  6. package/dist/cli/chat.js +258 -118
  7. package/dist/cli/chat.js.map +1 -1
  8. package/dist/cli/doctor.d.ts +31 -2
  9. package/dist/cli/doctor.d.ts.map +1 -1
  10. package/dist/cli/doctor.js +143 -7
  11. package/dist/cli/doctor.js.map +1 -1
  12. package/dist/cli/loop-executor.d.ts.map +1 -1
  13. package/dist/cli/loop-executor.js +4 -1
  14. package/dist/cli/loop-executor.js.map +1 -1
  15. package/dist/cli/parity.d.ts +12 -0
  16. package/dist/cli/parity.d.ts.map +1 -1
  17. package/dist/cli/parity.js +46 -1
  18. package/dist/cli/parity.js.map +1 -1
  19. package/dist/cli/tool-install-prompt.d.ts +2 -7
  20. package/dist/cli/tool-install-prompt.d.ts.map +1 -1
  21. package/dist/cli/tool-install-prompt.js +11 -28
  22. package/dist/cli/tool-install-prompt.js.map +1 -1
  23. package/dist/config/scratch-workspace.d.ts +134 -0
  24. package/dist/config/scratch-workspace.d.ts.map +1 -0
  25. package/dist/config/scratch-workspace.js +213 -0
  26. package/dist/config/scratch-workspace.js.map +1 -0
  27. package/dist/gateway/adapters.d.ts +24 -0
  28. package/dist/gateway/adapters.d.ts.map +1 -1
  29. package/dist/gateway/adapters.js +12 -0
  30. package/dist/gateway/adapters.js.map +1 -1
  31. package/dist/gateway/oversized-reply.d.ts +39 -0
  32. package/dist/gateway/oversized-reply.d.ts.map +1 -0
  33. package/dist/gateway/oversized-reply.js +54 -0
  34. package/dist/gateway/oversized-reply.js.map +1 -0
  35. package/dist/gateway/registry.d.ts +0 -10
  36. package/dist/gateway/registry.d.ts.map +1 -1
  37. package/dist/gateway/registry.js +148 -4
  38. package/dist/gateway/registry.js.map +1 -1
  39. package/dist/learning/quota-ledger.d.ts +24 -0
  40. package/dist/learning/quota-ledger.d.ts.map +1 -1
  41. package/dist/learning/quota-ledger.js +40 -0
  42. package/dist/learning/quota-ledger.js.map +1 -1
  43. package/dist/learning/runtime-dependencies.d.ts +183 -0
  44. package/dist/learning/runtime-dependencies.d.ts.map +1 -0
  45. package/dist/learning/runtime-dependencies.js +349 -0
  46. package/dist/learning/runtime-dependencies.js.map +1 -0
  47. package/dist/learning/skill-store.d.ts.map +1 -1
  48. package/dist/learning/skill-store.js +6 -5
  49. package/dist/learning/skill-store.js.map +1 -1
  50. package/dist/skills/bundled-skills-phase3.d.ts +14 -0
  51. package/dist/skills/bundled-skills-phase3.d.ts.map +1 -1
  52. package/dist/skills/bundled-skills-phase3.js +50 -0
  53. package/dist/skills/bundled-skills-phase3.js.map +1 -1
  54. package/dist/tools/modality/motion-presets.d.ts +62 -0
  55. package/dist/tools/modality/motion-presets.d.ts.map +1 -0
  56. package/dist/tools/modality/motion-presets.js +399 -0
  57. package/dist/tools/modality/motion-presets.js.map +1 -0
  58. package/dist/tools/modality/motion-tool.d.ts +62 -0
  59. package/dist/tools/modality/motion-tool.d.ts.map +1 -0
  60. package/dist/tools/modality/motion-tool.js +220 -0
  61. package/dist/tools/modality/motion-tool.js.map +1 -0
  62. package/dist/tools/modality/motion.d.ts +298 -0
  63. package/dist/tools/modality/motion.d.ts.map +1 -0
  64. package/dist/tools/modality/motion.js +514 -0
  65. package/dist/tools/modality/motion.js.map +1 -0
  66. package/dist/tools/registry.d.ts.map +1 -1
  67. package/dist/tools/registry.js +75 -0
  68. package/dist/tools/registry.js.map +1 -1
  69. package/dist/tools/tool-loop.d.ts.map +1 -1
  70. package/dist/tools/tool-loop.js +66 -16
  71. package/dist/tools/tool-loop.js.map +1 -1
  72. package/dist/tools/toolsets.js +2 -2
  73. package/dist/tools/toolsets.js.map +1 -1
  74. package/dist/utils/workspace-need.d.ts +84 -0
  75. package/dist/utils/workspace-need.d.ts.map +1 -0
  76. package/dist/utils/workspace-need.js +227 -0
  77. package/dist/utils/workspace-need.js.map +1 -0
  78. package/dist/web-dashboard/chat-console.d.ts +22 -0
  79. package/dist/web-dashboard/chat-console.d.ts.map +1 -1
  80. package/dist/web-dashboard/chat-console.js +65 -11
  81. package/dist/web-dashboard/chat-console.js.map +1 -1
  82. package/dist/web-dashboard/hub-data.d.ts +9 -1
  83. package/dist/web-dashboard/hub-data.d.ts.map +1 -1
  84. package/dist/web-dashboard/hub-data.js +2 -0
  85. package/dist/web-dashboard/hub-data.js.map +1 -1
  86. package/dist/web-dashboard/project-context.d.ts +1 -1
  87. package/dist/web-dashboard/project-context.d.ts.map +1 -1
  88. package/dist/web-dashboard/project-context.js +7 -1
  89. package/dist/web-dashboard/project-context.js.map +1 -1
  90. package/dist/web-dashboard/server.d.ts +33 -0
  91. package/dist/web-dashboard/server.d.ts.map +1 -1
  92. package/dist/web-dashboard/server.js +204 -21
  93. package/dist/web-dashboard/server.js.map +1 -1
  94. package/dist/web-dashboard/src/types.d.ts +46 -0
  95. package/dist/web-dashboard/src/types.d.ts.map +1 -1
  96. package/dist/web-dashboard/workspace-guard.d.ts +20 -21
  97. package/dist/web-dashboard/workspace-guard.d.ts.map +1 -1
  98. package/dist/web-dashboard/workspace-guard.js +20 -153
  99. package/dist/web-dashboard/workspace-guard.js.map +1 -1
  100. package/dist/web-dashboard/workspace-resolution.d.ts +23 -5
  101. package/dist/web-dashboard/workspace-resolution.d.ts.map +1 -1
  102. package/dist/web-dashboard/workspace-resolution.js +22 -4
  103. package/dist/web-dashboard/workspace-resolution.js.map +1 -1
  104. package/package.json +1 -1
  105. package/src/web-dashboard/public/assets/{index-DeSsNU94.css → index-CzRU84ET.css} +1 -1
  106. package/src/web-dashboard/public/assets/index-V0rIqVbg.js +236 -0
  107. package/src/web-dashboard/public/assets/index-V0rIqVbg.js.map +1 -0
  108. package/src/web-dashboard/public/index.html +2 -2
  109. package/src/web-dashboard/public/assets/index-Do_O67Kv.js +0 -236
  110. package/src/web-dashboard/public/assets/index-Do_O67Kv.js.map +0 -1
@@ -0,0 +1,84 @@
1
+ /**
2
+ * Does this ask need a workspace, and what does it need one FOR? — the rule,
3
+ * shared by every surface.
4
+ *
5
+ * WHY IT LIVES IN `utils/`. The rule started in `web-dashboard/workspace-guard.ts`
6
+ * because the dashboard was the first surface to refuse to guess a working
7
+ * directory: a chat turn with no folder inherited the SERVER PROCESS's cwd, so a
8
+ * service started from the home folder answered "assess this project" by
9
+ * describing whatever unrelated checkout sat in `~` — reported as "it went to
10
+ * kuttaaddon". Every surface now needs the same rule (the dashboard to resolve a
11
+ * workspace, the CLI's tool context, the messaging gateway, `ask_user` adopting a
12
+ * folder named in a reply), and `src/gateway`/`src/tools` must not depend on the
13
+ * dashboard — the same reason `utils/workspace-path.ts` exists. The dashboard's
14
+ * own module re-exports these, so its wording and its call sites are unchanged.
15
+ *
16
+ * The rule is deliberately NARROW. Chat is general-purpose: "write a haiku",
17
+ * "what's a monad", "summarise this text I pasted" must all keep working with no
18
+ * folder attached. Only asks that name a PROJECT, or that produce/consume files
19
+ * on disk, are gated.
20
+ *
21
+ * A second half was added after a report (2026-10-06): an ask that merely
22
+ * DESCRIBES work — a test scenario, a prompt, a spec, a project idea, "I want to
23
+ * test an agent on X" — is TEXT, and is answered inline even though it is full of
24
+ * development vocabulary. Gating it was the bug the user summarised as
25
+ * "intelligence is completely missing" about when a folder is required.
26
+ *
27
+ * The third half is {@link workspaceNeedForMissingFolder}: deciding WHETHER a
28
+ * folder is needed is not enough once a surface can resolve one. A produce ask
29
+ * can be served by a TEMPORARY folder; a read ask cannot, and must still ask.
30
+ */
31
+ /**
32
+ * True when this ask needs a workspace it does not have.
33
+ *
34
+ * The single decision about WHETHER a folder is required, so the message and the
35
+ * decision can never drift. {@link workspaceNeedForMissingFolder} builds on it to
36
+ * say what the folder is for.
37
+ */
38
+ export declare function needsProjectAttachment(message: string): boolean;
39
+ /**
40
+ * What an ask that has no workspace actually NEEDS one for.
41
+ *
42
+ * `null` — no folder is required at all (plain chat);
43
+ * `'produce'` — a place to PUT new work. An empty temporary folder serves this,
44
+ * which is what makes "create a script" answerable without
45
+ * dead-ending on a folder prompt;
46
+ * `'read'` — an existing tree to read or change ("assess this project", "fix
47
+ * the bug in src/app.ts"). NO temporary folder can serve this, and
48
+ * pretending otherwise is the silent-wrong-tree defect this rule
49
+ * exists to prevent — so those asks keep their folder prompt.
50
+ *
51
+ * WHY THE TWO HALVES ARE SEPARATE. `needsProjectAttachment` answers "does this
52
+ * ask need a workspace?" and its answer is used by a hard refusal. This one says
53
+ * what the workspace is FOR, so the surface can resolve one instead of refusing:
54
+ * a produce ask gets a scratch folder plus a notice "this is temporary, here is
55
+ * the path, say where you want it", and only a read ask still asks the user. The
56
+ * dashboard's reported misery ("agent keep going mad and confused when project
57
+ * folder not attached") was both halves being treated alike.
58
+ */
59
+ export type MissingWorkspaceNeed = 'read' | 'produce' | null;
60
+ /**
61
+ * Decide what this ask needs, for a turn that has no workspace.
62
+ *
63
+ * The order is the whole design, and it is conservative where it must be:
64
+ *
65
+ * 0. The VETOES come first, and they are the same ones `needsProjectAttachment`
66
+ * applies: a prose deliverable and a META ask ("I want to test an agent on
67
+ * build the application") are answered in TEXT and need no folder at all.
68
+ * Skipping this step is how "build the application" inside a capability
69
+ * description got a folder request — the reported "intelligence is
70
+ * completely missing" bug, in the first draft of this very function. → `null`.
71
+ * 1. A reference to work that ALREADY EXISTS ("this project", "our repo", "the
72
+ * app") outranks a creation verb — "create the project structure for a
73
+ * booking app" still names a project, and answering it in a temporary
74
+ * folder is the kuttaaddon defect in a new costume. → `'read'`.
75
+ * 2. Otherwise a create-shaped ask (a creation verb on an artifact noun, a
76
+ * producing verb aimed at an explicit file, or media generation) can be
77
+ * served by a temporary folder. → `'produce'`.
78
+ * 3. Otherwise fall back to the guard's own verdict: if it needs a folder and
79
+ * no creation verb explains why, it needs the real tree. → `'read'`.
80
+ * 4. Otherwise the ask needs nothing. → `null`, and the surface behaves exactly
81
+ * as it did before scratch existed.
82
+ */
83
+ export declare function workspaceNeedForMissingFolder(message: string): MissingWorkspaceNeed;
84
+ //# sourceMappingURL=workspace-need.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workspace-need.d.ts","sourceRoot":"","sources":["../../src/utils/workspace-need.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAiIH;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAuB/D;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,MAAM,oBAAoB,GAAG,MAAM,GAAG,SAAS,GAAG,IAAI,CAAC;AAc7D;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,6BAA6B,CAAC,OAAO,EAAE,MAAM,GAAG,oBAAoB,CAiBnF"}
@@ -0,0 +1,227 @@
1
+ /**
2
+ * Does this ask need a workspace, and what does it need one FOR? — the rule,
3
+ * shared by every surface.
4
+ *
5
+ * WHY IT LIVES IN `utils/`. The rule started in `web-dashboard/workspace-guard.ts`
6
+ * because the dashboard was the first surface to refuse to guess a working
7
+ * directory: a chat turn with no folder inherited the SERVER PROCESS's cwd, so a
8
+ * service started from the home folder answered "assess this project" by
9
+ * describing whatever unrelated checkout sat in `~` — reported as "it went to
10
+ * kuttaaddon". Every surface now needs the same rule (the dashboard to resolve a
11
+ * workspace, the CLI's tool context, the messaging gateway, `ask_user` adopting a
12
+ * folder named in a reply), and `src/gateway`/`src/tools` must not depend on the
13
+ * dashboard — the same reason `utils/workspace-path.ts` exists. The dashboard's
14
+ * own module re-exports these, so its wording and its call sites are unchanged.
15
+ *
16
+ * The rule is deliberately NARROW. Chat is general-purpose: "write a haiku",
17
+ * "what's a monad", "summarise this text I pasted" must all keep working with no
18
+ * folder attached. Only asks that name a PROJECT, or that produce/consume files
19
+ * on disk, are gated.
20
+ *
21
+ * A second half was added after a report (2026-10-06): an ask that merely
22
+ * DESCRIBES work — a test scenario, a prompt, a spec, a project idea, "I want to
23
+ * test an agent on X" — is TEXT, and is answered inline even though it is full of
24
+ * development vocabulary. Gating it was the bug the user summarised as
25
+ * "intelligence is completely missing" about when a folder is required.
26
+ *
27
+ * The third half is {@link workspaceNeedForMissingFolder}: deciding WHETHER a
28
+ * folder is needed is not enough once a surface can resolve one. A produce ask
29
+ * can be served by a TEMPORARY folder; a read ask cannot, and must still ask.
30
+ */
31
+ /**
32
+ * Asks that clearly target "the project/codebase" the reader is supposedly
33
+ * looking at — the phrase that started this: "assess this project".
34
+ */
35
+ const PROJECT_REFERENCE_RE = /\b(?:this|the|my|our|current)\s+(?:project|repo|repository|codebase|code\s?base|workspace|app|application|code|folder|directory|solution)\b/i;
36
+ /** Project work: assess / review / refactor / fix / debug / test / build / audit… */
37
+ const PROJECT_WORK_RE = /\b(?:assess|assessment|review|audit|analyse|analyze|evaluate|inspect|examine|explore|refactor|debug|diagnose|fix|repair|migrate|upgrade|optimi[sz]e|document|test|build|compile|lint|typecheck|type-?check|run\s+the\s+tests?|set\s?up|scaffold|bootstrap)\b/i;
38
+ /** A project-ish noun that pairs with {@link PROJECT_WORK_RE}. */
39
+ const PROJECT_NOUN_RE = /\b(?:project|repo|repository|codebase|code\s?base|workspace|source|backend|frontend|api|server|cli|app|application|service|package|monorepo|tests?|suite|branch|dependencies)\b/i;
40
+ /**
41
+ * Filesystem deliverables: making or changing files on disk. These need a
42
+ * directory to land in whether or not the ask says "project".
43
+ *
44
+ * NOTE the nouns are artifacts that exist ON DISK. `class` was removed after it
45
+ * matched a school sense: "write an essay … for **class** 4" was read as
46
+ * "write a code class" and gated behind a folder prompt it did not need. A bare
47
+ * "class" is inherently ambiguous — code vs. school — so it is not evidence a
48
+ * directory is required.
49
+ */
50
+ const FILESYSTEM_TASK_RE = /\b(?:create|write|make|add|generate|produce|build|edit|modify|update|patch|rename|move|delete|remove|save|export|append)\b[^.!?\n]{0,60}\b(?:file|files|folder|folders|directory|directories|script|module|component|document|markdown|readme|report|image|picture|photo|logo|diagram|chart|plot|icon|screenshot|video|audio)\b/i;
51
+ /**
52
+ * INLINE PROSE deliverables — an essay, a poem, a story, a letter. General
53
+ * chat produces these in the reply with no workspace at all, so they must never
54
+ * be gated, even when the request incidentally contains a code-ish word
55
+ * ("an essay on elephants for a **class** 4 student") or a file-ish noun
56
+ * ("write a **summary**").
57
+ *
58
+ * This is the user-reported false positive: after being asked to attach a folder
59
+ * once, an essay question was refused for the same reason, which read as the
60
+ * agent having stopped listening. Only an EXPLICIT file artifact (a named file,
61
+ * `.md`, a folder, a directory) overrides this and keeps the ask gated.
62
+ */
63
+ const INLINE_PROSE_RE = /\b(?:write|compose|draft|create|make|produce|prepare)\b[^.!?\n]{0,40}\b(?:essay|poem|story|haiku|paragraph|letter|email|article|speech|assignment|homework|answer|explanation|description|summary|short\s+note|blurb|bio|memo)\b/i;
64
+ /** An explicit on-disk artifact — the only thing that overrides INLINE_PROSE_RE. */
65
+ const EXPLICIT_FILE_RE = /\b(?:file|files|folder|folders|directory|directories|path|\.md\b|\.txt\b|\.json\b|\.csv\b|\.docx?\b|\.pdf\b|readme|document)\b/i;
66
+ /**
67
+ * A producing verb aimed at an explicit on-disk artifact ("save it as poem.txt",
68
+ * "write the essay to essay.md"). This is what makes a PROSE deliverable a
69
+ * workspace task after all — the write target is a file, not the reply.
70
+ */
71
+ const FILE_PRODUCING_RE = /\b(?:write|create|save|export|produce|generate|make|draft|compose|append)\b[^.!?\n]{0,40}\b(?:file|folder|directory|path|\.md\b|\.txt\b|\.json\b|\.csv\b|\.docx?\b|\.pdf\b)\b/i;
72
+ /** Media generation, phrased as a verb on the media itself ("generate an image"). */
73
+ const MEDIA_TASK_RE = /\b(?:generate|create|make|draw|render|design|produce)\b[^.!?\n]{0,40}\b(?:an?\s+)?(?:image|picture|photo|logo|diagram|chart|plot|icon|illustration|artwork|banner|thumbnail|video|audio|voiceover)\b/i;
74
+ // ─── META / INSTRUCTIONAL asks ──────────────────────────────────────────────
75
+ //
76
+ // The user is asking for a DESCRIPTION of work rather than the work itself: a
77
+ // test scenario, a prompt, a spec, a project idea, a capability challenge. The
78
+ // development vocabulary inside those asks names the SUBJECT, not the action,
79
+ // so no workspace is required — even when a producing verb appears ("…build the
80
+ // application…").
81
+ //
82
+ // THIS IS THE REPORTED BUG (2026-10-06). A user asked the dashboard chat to
83
+ // produce a project they could use to TEST an agent on a large, phased
84
+ // capability (planning → development → testing → docs → tool installs → build
85
+ // → git). The guard read "build the application" — a producing verb on a
86
+ // project noun — and refused with the folder prompt. The clarification "this
87
+ // is not a development ask - i need text" was refused IDENTICALLY, because the
88
+ // guard never looked at the FRAME of the request, only at the verbs and nouns
89
+ // buried inside it. The user's summary: "intelligence is completely missing"
90
+ // around when a folder is required and when it is not.
91
+ /**
92
+ * "I want to test an agent on … capability" — the ask is about evaluating the
93
+ * agent, which is answered with text (a scenario/spec), never by opening a
94
+ * folder. Requires an intent-to-test frame so a bare "test my agent's code"
95
+ * (which may well mean an attached checkout) is not swept up.
96
+ */
97
+ const META_AGENT_TEST_RE = /\b(?:want|need|plan(?:ning)?|intend|would\s+like|trying|going|help(?:\s+me)?|how\s+to|how\s+do\s+i|i\s+am|i'?m)\b[^.!?\n]{0,40}\b(?:test|testing|evaluate|evaluating|benchmark(?:ing)?|assess(?:ing)?|challenge|validate|stress[- ]?test)\b[^.!?\n]{0,50}\b(?:an?|the|my|our|your)\s+(?:ai\s+|coding\s+|development\s+|software\s+|autonomous\s+)?agents?\b/i;
98
+ /** "give me a test scenario / a prompt / a spec / a project idea" — a content deliverable, answered inline. */
99
+ const REQUEST_FOR_SCENARIO_RE = /\b(?:give|provide|suggest|design|create|write|draft|generate|propose|come\s+up\s+with|share|need|want)\b[^.!?\n]{0,30}\b(?:prompt|scenario|test\s+case|test\s+plan|test\s+suite|benchmark|spec|specification|project\s+idea|project\s+spec|example\s+project|sample\s+project|use\s+case|exercise|task\s+description|evaluation\s+rubric|rubric)\b/i;
100
+ /** "a project which will require this" — an indefinite, hypothetical project, not a folder the user points at. */
101
+ const HYPOTHETICAL_PROJECT_RE = /\b(?:a|some|any)\s+(?:project|app|application|system|tool|service|repo(?:sitory)?|codebase)\b[^.!?\n]{0,40}\b(?:that|which)\b[^.!?\n]{0,40}\b(?:requires?|would\s+require|will\s+require|needs?|would\s+need|involves?|entails?|would\s+involve)\b/i;
102
+ /** An explicit statement that the user wants TEXT, not code — decisive on its own. */
103
+ const TEXT_ONLY_RE = /\b(?:i\s+(?:just\s+)?need(?:ed)?\s+(?:the\s+)?text|just\s+the\s+text|only\s+(?:the\s+)?text|text\s+only|no\s+code|without\s+(?:any\s+)?code|need\s+text|not\s+a\s+(?:development|coding|code|software|programming)\s+(?:ask|task|request|question|exercise|work)|this\s+is\s+not\s+a\s+development|no\s+development\s+needed|nothing\s+to\s+(?:build|code|develop|implement))\b/i;
104
+ /**
105
+ * A reference to a REAL workspace the user points AT ("this project", "our
106
+ * repo"). When present the ask is about a folder, so the meta rules stand down
107
+ * — "test this project" is still a workspace ask.
108
+ */
109
+ const DEICTIC_WORKSPACE_RE = /\b(?:this|my|our|the\s+current|current)\s+(?:project|repo|repository|codebase|code\s?base|workspace|solution)\b/i;
110
+ /**
111
+ * True when this ask only DESCRIBES work — a scenario, spec, prompt, capability
112
+ * challenge, or a plain request for text — rather than asking to perform it.
113
+ *
114
+ * Order matters: an explicit on-disk artifact always wins ("write the scenario
115
+ * to scenario.md" is a workspace ask), then an explicit "I need text" wins over
116
+ * a deictic mention (the user's own clarification said "this project" while
117
+ * explicitly asking for text), then a deictic workspace reference otherwise
118
+ * vetoes the meta rules.
119
+ */
120
+ function isMetaOrTextAsk(text) {
121
+ if (EXPLICIT_FILE_RE.test(text))
122
+ return false;
123
+ if (TEXT_ONLY_RE.test(text))
124
+ return true;
125
+ if (DEICTIC_WORKSPACE_RE.test(text))
126
+ return false;
127
+ return (META_AGENT_TEST_RE.test(text) ||
128
+ REQUEST_FOR_SCENARIO_RE.test(text) ||
129
+ HYPOTHETICAL_PROJECT_RE.test(text));
130
+ }
131
+ /**
132
+ * True when this ask needs a workspace it does not have.
133
+ *
134
+ * The single decision about WHETHER a folder is required, so the message and the
135
+ * decision can never drift. {@link workspaceNeedForMissingFolder} builds on it to
136
+ * say what the folder is for.
137
+ */
138
+ export function needsProjectAttachment(message) {
139
+ const text = (message ?? '').trim();
140
+ if (!text)
141
+ return false;
142
+ // A URL or an absolute path names its own subject — the user is being
143
+ // specific, so asking them to "attach a folder" would be noise.
144
+ if (/(?:^|[\s("'`])(?:\/|~\/|https?:\/\/|www\.)/.test(text))
145
+ return false;
146
+ // A prose deliverable is answered inline; only an explicit file artifact in
147
+ // the same message makes it a workspace task. Checked BEFORE the project/work
148
+ // rules so an incidental code-ish noun cannot gate an essay or a poem.
149
+ if (INLINE_PROSE_RE.test(text) && !EXPLICIT_FILE_RE.test(text))
150
+ return false;
151
+ // A META ask describes work instead of doing it — a test scenario, a prompt,
152
+ // a spec, a project idea, or plainly "I need text". The development words in
153
+ // it name the SUBJECT, so answer inline rather than demanding a folder. This
154
+ // is the fix for the reported "test an agent on <capability>" refusal.
155
+ if (isMetaOrTextAsk(text))
156
+ return false;
157
+ // A named file target means it lands on disk even if the content is prose.
158
+ if (FILE_PRODUCING_RE.test(text))
159
+ return true;
160
+ if (PROJECT_REFERENCE_RE.test(text))
161
+ return true;
162
+ if (FILESYSTEM_TASK_RE.test(text))
163
+ return true;
164
+ if (MEDIA_TASK_RE.test(text))
165
+ return true;
166
+ // Project WORK plus a project-ish noun anywhere ("review the backend code").
167
+ if (PROJECT_WORK_RE.test(text) && PROJECT_NOUN_RE.test(text))
168
+ return true;
169
+ return false;
170
+ }
171
+ /**
172
+ * A creation verb aimed at an artifact the agent can CREATE from nothing.
173
+ *
174
+ * The verbs are the create half of {@link FILESYSTEM_TASK_RE} (nothing here is
175
+ * an edit — "fix", "update" and "refactor" all require something to already
176
+ * exist, so they belong to the read half). The nouns are the artifact kinds a
177
+ * fresh folder can legitimately hold, including the project-shaped ones a user
178
+ * asks for by name ("create a react app").
179
+ */
180
+ const CREATE_ARTIFACT_RE = /\b(?:create|write|make|add|generate|produce|build|save|export|append|draw|render|design|draft|compose)\b[^.!?\n]{0,60}\b(?:file|files|folder|folders|directory|directories|script|program|module|component|document|doc|docs|markdown|readme|report|guide|note|notes|text|table|spreadsheet|json|csv|md|txt|pdf|html|css|image|picture|photo|logo|diagram|chart|plot|icon|screenshot|video|audio|poem|essay|story|letter|post|article|app|application|website|site|webpage|web\s?page|service|api|endpoint|server|cli|tool|game|bot)\b/i;
181
+ /**
182
+ * Decide what this ask needs, for a turn that has no workspace.
183
+ *
184
+ * The order is the whole design, and it is conservative where it must be:
185
+ *
186
+ * 0. The VETOES come first, and they are the same ones `needsProjectAttachment`
187
+ * applies: a prose deliverable and a META ask ("I want to test an agent on
188
+ * build the application") are answered in TEXT and need no folder at all.
189
+ * Skipping this step is how "build the application" inside a capability
190
+ * description got a folder request — the reported "intelligence is
191
+ * completely missing" bug, in the first draft of this very function. → `null`.
192
+ * 1. A reference to work that ALREADY EXISTS ("this project", "our repo", "the
193
+ * app") outranks a creation verb — "create the project structure for a
194
+ * booking app" still names a project, and answering it in a temporary
195
+ * folder is the kuttaaddon defect in a new costume. → `'read'`.
196
+ * 2. Otherwise a create-shaped ask (a creation verb on an artifact noun, a
197
+ * producing verb aimed at an explicit file, or media generation) can be
198
+ * served by a temporary folder. → `'produce'`.
199
+ * 3. Otherwise fall back to the guard's own verdict: if it needs a folder and
200
+ * no creation verb explains why, it needs the real tree. → `'read'`.
201
+ * 4. Otherwise the ask needs nothing. → `null`, and the surface behaves exactly
202
+ * as it did before scratch existed.
203
+ */
204
+ export function workspaceNeedForMissingFolder(message) {
205
+ const text = (message ?? '').trim();
206
+ if (!text)
207
+ return null;
208
+ // A URL or an absolute path names its own subject (and the caller resolves the
209
+ // path itself — see `directoryFromMessage`), so this rule must not fire.
210
+ if (/(?:^|[\s("'`])(?:\/|~\/|https?:\/\/|www\.)/.test(text))
211
+ return null;
212
+ // 0 — the text/meta vetoes, BEFORE the project and create rules below, because a
213
+ // description of work must never be answered with a folder request or a scratch
214
+ // folder. These are `needsProjectAttachment`'s own first two checks, in its own
215
+ // order, so the two functions cannot disagree about what is even eligible.
216
+ if (INLINE_PROSE_RE.test(text) && !EXPLICIT_FILE_RE.test(text))
217
+ return null;
218
+ if (isMetaOrTextAsk(text))
219
+ return null;
220
+ if (PROJECT_REFERENCE_RE.test(text))
221
+ return 'read';
222
+ if (FILE_PRODUCING_RE.test(text) || MEDIA_TASK_RE.test(text) || CREATE_ARTIFACT_RE.test(text)) {
223
+ return 'produce';
224
+ }
225
+ return needsProjectAttachment(text) ? 'read' : null;
226
+ }
227
+ //# sourceMappingURL=workspace-need.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workspace-need.js","sourceRoot":"","sources":["../../src/utils/workspace-need.ts"],"names":[],"mappings":"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"}
@@ -280,6 +280,20 @@ export interface ChatSessionRecord {
280
280
  */
281
281
  pinnedProvider?: string;
282
282
  pinnedModel?: string;
283
+ /**
284
+ * P8b — the STRICT half of that pin: "this model or nothing".
285
+ *
286
+ * The pin and the strict flag are ONE decision — the client sends them
287
+ * together and the engine reads them together (a strict turn refuses to
288
+ * substitute; a mere pin still allows auto-routing to take over). Persisting
289
+ * only the pin was measured live (trace-1792068695325-42wb1j): the chat came
290
+ * back pinned to `deepseek/deepseek-v4-pro` with strict silently OFF, so the
291
+ * engine handed the turn to `local/deepseek-coder:latest` and the user's own
292
+ * "this model only" instruction was never in force. Stored beside the pin,
293
+ * cleared with it when Auto is chosen (`undefined` = off, never `false`, so a
294
+ * record written before this field existed reads as off).
295
+ */
296
+ pinnedStrict?: boolean;
283
297
  }
284
298
  /** P4 — the sidebar summary shape for `GET /api/sessions`. */
285
299
  export interface ChatSessionSummary {
@@ -619,6 +633,14 @@ export declare class ChatConsole {
619
633
  worktree?: boolean;
620
634
  keepWorktree?: boolean;
621
635
  resume?: string | boolean;
636
+ /**
637
+ * P8b — the STRICT half of a pin (the chat's "pin this model only"
638
+ * switch). Scoped to the turn by the server's `withStrictModel`; carried
639
+ * here as well so the CONVERSATION can remember the choice and so a turn
640
+ * this console starts on its own (the deferred retry) honours the pin the
641
+ * user set rather than re-deriving it. Absent = off.
642
+ */
643
+ strict?: boolean;
622
644
  }): Promise<ChatAnswerResult>;
623
645
  /**
624
646
  * Phase 4 — invoke the turn-completion hook (the DAG store's endLoopTurn
@@ -1 +1 @@
1
- {"version":3,"file":"chat-console.d.ts","sourceRoot":"","sources":["../../src/web-dashboard/chat-console.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"chat-console.d.ts","sourceRoot":"","sources":["../../src/web-dashboard/chat-console.ts"],"names":[],"mappings":"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"}
@@ -20,10 +20,36 @@ import { isSuggestedFollowup, normalizeFollowups } from '../tools/followup-utils
20
20
  import { looksLikeReasoningLeakReply, stripLeadingReasoningTrace, stripToolCallArtifacts, } from '../inference/tool-call-utils.js';
21
21
  import { createPersistentPlanStore, planFilePath, writePlanFile, } from '../tools/plan-store.js';
22
22
  import { getSessionGrant, clearSessionGrant } from '../learning/session-grant.js';
23
+ import { withStrictModel } from '../inference/route-resolver.js';
23
24
  /** Per-session per-message limits (the CLI has no hard cap; bound the server). */
24
25
  const MAX_MESSAGE_LENGTH = 8000;
25
26
  const DEFAULT_MAX_TURNS = 40;
26
27
  const DEFAULT_MAX_SESSIONS = 50;
28
+ /**
29
+ * The PIN a request carries, in record shape — `undefined` when the client sent
30
+ * no model (an Auto turn, which clears any stored pin).
31
+ *
32
+ * P8b — provider, model and the strict half are read as ONE value because they
33
+ * are one decision: the chat's picker sets the pair, its lock sets `strict`, and
34
+ * the engine consumes them together (a strict turn refuses to substitute; a
35
+ * bare pin still lets auto-routing take over). Writing them through separate
36
+ * code paths is exactly how the pair survived a reload while the lock did not
37
+ * (trace-1792068695325-42wb1j: pinned to `deepseek/deepseek-v4-pro`, strict
38
+ * silently off, turn handed to `local/deepseek-coder:latest`).
39
+ *
40
+ * `pinnedStrict: false` is never stored — the absence of the field IS "off", so
41
+ * a record written before the field existed reads the same as one where the
42
+ * user turned the lock off.
43
+ */
44
+ function pinOf(opts) {
45
+ if (!opts.provider || !opts.model)
46
+ return undefined;
47
+ return {
48
+ pinnedProvider: opts.provider,
49
+ pinnedModel: opts.model,
50
+ ...(opts.strict === true ? { pinnedStrict: true } : {}),
51
+ };
52
+ }
27
53
  export class ChatConsole {
28
54
  opts;
29
55
  sessions = new Map();
@@ -76,7 +102,7 @@ export class ChatConsole {
76
102
  for (const [id, rec] of Object.entries(data?.sessions ?? {})) {
77
103
  if (typeof id !== 'string' || !id || !rec || !Array.isArray(rec.turns))
78
104
  continue;
79
- this.sessions.set(id, { turns: rec.turns, title: String(rec.title ?? ''), createdAt: Number(rec.createdAt) || 0, updatedAt: Number(rec.updatedAt) || 0, ...(typeof rec.projectPath === 'string' && rec.projectPath ? { projectPath: rec.projectPath } : {}), ...(Array.isArray(rec.followups) && rec.followups.length > 0 ? { followups: normalizeFollowups(rec.followups) } : {}), ...(typeof rec.pinnedProvider === 'string' && rec.pinnedProvider && typeof rec.pinnedModel === 'string' && rec.pinnedModel ? { pinnedProvider: rec.pinnedProvider, pinnedModel: rec.pinnedModel } : {}) });
105
+ this.sessions.set(id, { turns: rec.turns, title: String(rec.title ?? ''), createdAt: Number(rec.createdAt) || 0, updatedAt: Number(rec.updatedAt) || 0, ...(typeof rec.projectPath === 'string' && rec.projectPath ? { projectPath: rec.projectPath } : {}), ...(Array.isArray(rec.followups) && rec.followups.length > 0 ? { followups: normalizeFollowups(rec.followups) } : {}), ...(typeof rec.pinnedProvider === 'string' && rec.pinnedProvider && typeof rec.pinnedModel === 'string' && rec.pinnedModel ? { pinnedProvider: rec.pinnedProvider, pinnedModel: rec.pinnedModel } : {}), ...(rec.pinnedStrict === true ? { pinnedStrict: true } : {}) });
80
106
  }
81
107
  }
82
108
  catch {
@@ -241,6 +267,7 @@ export class ChatConsole {
241
267
  ...(existing?.projectPath ? { projectPath: existing.projectPath } : {}),
242
268
  ...(existing?.followups && existing.followups.length > 0 ? { followups: existing.followups } : {}),
243
269
  ...(existing?.pinnedProvider && existing.pinnedModel ? { pinnedProvider: existing.pinnedProvider, pinnedModel: existing.pinnedModel } : {}),
270
+ ...(existing?.pinnedStrict === true ? { pinnedStrict: true } : {}),
244
271
  });
245
272
  this.persist();
246
273
  }
@@ -319,9 +346,10 @@ export class ChatConsole {
319
346
  // only includes them when a model is pinned (Auto sends neither), so
320
347
  // their absence on a recorded turn means "Auto" and CLEARS any pin. A
321
348
  // non-recorded turn (the deferred-retry broker) never touches the pin.
322
- const pinnedPatch = opts.provider && opts.model
323
- ? { pinnedProvider: opts.provider, pinnedModel: opts.model }
324
- : {};
349
+ // P8b — the strict flag rides WITH the pin: both are set together and
350
+ // both are dropped together, so "off" is the absence of the field rather
351
+ // than a stored `false` that could outlive the pin it belongs to.
352
+ const pinnedPatch = pinOf(opts) ?? {};
325
353
  this.sessions.set(sessionId, {
326
354
  turns: history,
327
355
  title: existing?.title ?? '',
@@ -332,6 +360,22 @@ export class ChatConsole {
332
360
  ...pinnedPatch,
333
361
  });
334
362
  }
363
+ // ══ P8b — WHICH PIN THIS TURN ACTUALLY OBEYS ═══════════════════════════
364
+ // The request's pin wins. A turn with NO pin in the request is Auto for a
365
+ // recorded turn (and clears the stored pin), but a turn this console starts
366
+ // itself — the deferred-retry broker, `recordTurn: false` — carries no pin
367
+ // of its own and must therefore inherit the one the conversation is already
368
+ // pinned to. Otherwise a retry of a strictly-pinned turn silently ran
369
+ // AUTO-routed, which is the same defect class as the strict flag itself
370
+ // being forgotten (trace-1792068695325-42wb1j).
371
+ const requestedPin = pinOf(opts);
372
+ const activePin = requestedPin
373
+ ? { provider: requestedPin.pinnedProvider, model: requestedPin.pinnedModel, strict: requestedPin.pinnedStrict === true }
374
+ : recordTurn
375
+ ? undefined
376
+ : existing?.pinnedProvider && existing.pinnedModel
377
+ ? { provider: existing.pinnedProvider, model: existing.pinnedModel, strict: existing.pinnedStrict === true }
378
+ : undefined;
335
379
  this.busy.add(sessionId);
336
380
  // The turn's own start, so a client that gave up waiting can say how old the
337
381
  // wait actually is (see `turnStartedAt`).
@@ -352,7 +396,10 @@ export class ChatConsole {
352
396
  // Phase 4 — begin the DAG turn telemetry window (engine badge 'loop',
353
397
  // per-tool telemetry accumulates below).
354
398
  try {
355
- this.turnTelemetry?.beginLoopTurn(`${sessionId}-${now}`, clean, opts.provider, opts.model);
399
+ this.turnTelemetry?.beginLoopTurn(`${sessionId}-${now}`, clean,
400
+ // The pin the turn actually obeys (a deferred retry inherits the stored
401
+ // one), so the telemetry names the pair the engine was handed.
402
+ activePin?.provider ?? opts.provider, activePin?.model ?? opts.model);
356
403
  }
357
404
  catch {
358
405
  /* telemetry must never break the turn */
@@ -362,7 +409,13 @@ export class ChatConsole {
362
409
  // WS1 — the findings this turn records, collected from the engine's
363
410
  // `onFinding` seam (the same event the CLI and the gateway hear).
364
411
  const findings = [];
365
- const answer = await engine.answerOnce(clean, {
412
+ // P8b — the pin's STRICT half is enforced around the engine call itself,
413
+ // not only by the server's route handler: a turn this console starts on its
414
+ // own (the deferred retry) never passes through that handler, so without
415
+ // this wrap a strictly-pinned conversation could still be substituted on a
416
+ // background retry. Nesting inside the server's own `withStrictModel` is
417
+ // harmless — the inner scope wins and carries the same value.
418
+ const answer = await withStrictModel(activePin?.strict === true, () => engine.answerOnce(clean, {
366
419
  // P4 — the cancel signal rides into the turn.
367
420
  signal: controller.signal,
368
421
  // WS1 — a recorded finding, forwarded live and kept for the result.
@@ -385,8 +438,8 @@ export class ChatConsole {
385
438
  worktree: opts.worktree,
386
439
  keepWorktree: opts.keepWorktree,
387
440
  resume: opts.resume,
388
- ...(opts.provider ? { provider: opts.provider } : {}),
389
- ...(opts.model ? { model: opts.model } : {}),
441
+ ...(activePin ? { provider: activePin.provider } : {}),
442
+ ...(activePin ? { model: activePin.model } : {}),
390
443
  // P5 — a followup chip continues the previous execution.
391
444
  ...(continuation ? { continuation: true } : {}),
392
445
  // P3 — project context rides into the turn (the engine injects it as
@@ -489,7 +542,7 @@ export class ChatConsole {
489
542
  });
490
543
  },
491
544
  planStore: this.planStoreFor(sessionId),
492
- });
545
+ }));
493
546
  // P4 — a cancelled turn is DISCARDED entirely: no session write, no
494
547
  // persist, no status:done, no events (the client already walked away
495
548
  // and may have started a new turn). abort() released busy immediately.
@@ -524,8 +577,9 @@ export class ChatConsole {
524
577
  ...(opts.projectPath ? { projectPath: opts.projectPath } : (existing?.projectPath ? { projectPath: existing.projectPath } : {})),
525
578
  ...(nextFollowups.length > 0 ? { followups: nextFollowups } : {}),
526
579
  // P8 — the completed turn keeps the pin (and an Auto turn clears it),
527
- // the same rule the pre-turn record write applies.
528
- ...(opts.provider && opts.model ? { pinnedProvider: opts.provider, pinnedModel: opts.model } : {}),
580
+ // the same rule the pre-turn record write applies. P8b — strict rides
581
+ // with it.
582
+ ...(pinOf(opts) ?? {}),
529
583
  });
530
584
  this.persist();
531
585
  }