@lazyingart/agintiflow 0.20.182 → 0.20.183

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 CHANGED
@@ -153,7 +153,7 @@ aginti --language de
153
153
  | Save provider keys | `aginti auth`, `/auth`, `/login` |
154
154
  | Review current repo | `/review [focus]` |
155
155
  | Toggle SCS quality gate | `/scs` |
156
- | Use SCS only for complex work | `/scs auto` or `aginti --scs auto "task"` |
156
+ | Keep default auto SCS routing | `/scs auto` or `aginti --scs auto "task"` |
157
157
  | Disable SCS for simple work | `/scs off` or `aginti --no-scs "task"` |
158
158
  | Control dynamic step budgets | `--dynamic-steps auto\|on\|off` |
159
159
  | Work with AAPS workflows | `aginti aaps status`, `/aaps validate` |
@@ -61,13 +61,13 @@ The current implementation is deliberately bounded:
61
61
 
62
62
  ## Auto Mode
63
63
 
64
- `/scs auto` and `--scs auto` are still available when a user wants cheaper routing for simple turns. Auto mode activates SCS for complex, risky, or long-running work. Signals include:
64
+ `/scs auto` and `--scs auto` are the default for users who want cheap simple turns without losing strict validation on risky work. Auto mode activates SCS for high-risk, evidence-heavy, or long-running work. Signals include:
65
65
 
66
- - high smart-routing complexity score;
67
- - profiles such as code, app, Android/iOS, large-codebase, GitHub, maintenance, security, LaTeX, research, and supervision;
68
- - prompts mentioning multi-file work, regressions, builds, deployments, tmux, emulators, Docker, PDFs, or similar high-friction workflows.
66
+ - very high smart-routing complexity score;
67
+ - profiles such as app, Android/iOS, large-codebase, GitHub, maintenance, QA, security, supervision, pipeline, and website;
68
+ - prompts mentioning failing tests, repo-wide changes, browser uploads, releases, deployments, tmux, emulators, Docker, PDFs, or similar high-friction workflows.
69
69
 
70
- Auto mode stays off for simple turns, but it is not the default.
70
+ Auto mode is the default. It stays off for simple turns, uses the main model for moderate complexity, and activates SCS only for high-risk or evidence-heavy turns.
71
71
 
72
72
  ## Dynamic Step Budgets
73
73
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lazyingart/agintiflow",
3
- "version": "0.20.182",
3
+ "version": "0.20.183",
4
4
  "type": "module",
5
5
  "description": "AgInTiFlow is a project-aware agent workspace for hybrid wet-dry R&D, hardware-aware intelligence, software automation, and industrial workflows.",
6
6
  "license": "Apache-2.0",
package/public/app.js CHANGED
@@ -1402,7 +1402,7 @@ function syncQuickModeControls() {
1402
1402
  if (aapsModeToggle) aapsModeToggle.checked = (taskProfileField?.value || "auto") === "aaps";
1403
1403
  if (veniceModeToggle) veniceModeToggle.checked = quickVeniceModeActive;
1404
1404
  if (quickModeStatusEl) {
1405
- const scs = enableScsField?.value || "on";
1405
+ const scs = enableScsField?.value || "auto";
1406
1406
  const profile = taskProfileField?.value || "auto";
1407
1407
  const route = `${routeProviderField?.value || "deepseek"}/${fieldValue(routeModelField) || "auto"}`;
1408
1408
  const main = `${mainProviderField?.value || "deepseek"}/${fieldValue(mainModelField) || "auto"}`;
@@ -1451,8 +1451,8 @@ function applyVeniceMode(enabled) {
1451
1451
  syncQuickModeControls();
1452
1452
  }
1453
1453
 
1454
- function applyScsMode(mode = enableScsField?.value || "on") {
1455
- if (enableScsField) enableScsField.value = ["on", "auto", "off"].includes(mode) ? mode : "on";
1454
+ function applyScsMode(mode = enableScsField?.value || "auto") {
1455
+ if (enableScsField) enableScsField.value = ["on", "auto", "off"].includes(mode) ? mode : "auto";
1456
1456
  if (allowParallelScoutsField && enableScsField?.value === "on") {
1457
1457
  allowParallelScoutsField.checked = false;
1458
1458
  }
@@ -1707,7 +1707,7 @@ function formPayload() {
1707
1707
  allowWebSearch: allowWebSearchField?.checked ?? true,
1708
1708
  allowMcpTools: allowMcpToolsField?.checked ?? true,
1709
1709
  allowParallelScouts: allowParallelScoutsField?.checked ?? true,
1710
- enableScs: enableScsField?.value || "on",
1710
+ enableScs: enableScsField?.value || "auto",
1711
1711
  dynamicSteps: dynamicStepsField?.value || "auto",
1712
1712
  veniceMode: quickVeniceModeActive,
1713
1713
  parallelScoutCount: Math.min(Math.max(Number(parallelScoutCountField?.value) || 3, 1), 10),
@@ -3818,7 +3818,7 @@ async function loadConfig() {
3818
3818
  if (allowWebSearchField) allowWebSearchField.checked = prefs.allowWebSearch ?? true;
3819
3819
  if (allowMcpToolsField) allowMcpToolsField.checked = prefs.allowMcpTools ?? true;
3820
3820
  if (allowParallelScoutsField) allowParallelScoutsField.checked = prefs.allowParallelScouts ?? true;
3821
- if (enableScsField) enableScsField.value = prefs.enableScs || "on";
3821
+ if (enableScsField) enableScsField.value = prefs.enableScs || "auto";
3822
3822
  if (dynamicStepsField) dynamicStepsField.value = prefs.dynamicSteps || "auto";
3823
3823
  if (parallelScoutCountField) parallelScoutCountField.value = String(prefs.parallelScoutCount || 3);
3824
3824
  allowWrapperToolsField.checked = prefs.allowWrapperTools ?? false;
package/public/index.html CHANGED
@@ -264,8 +264,8 @@
264
264
  <label class="quick-mode-select">
265
265
  <span data-i18n="scsModeLabel">SCS</span>
266
266
  <select id="enableScs" name="enableScs">
267
- <option value="on" data-i18n="scsOnOption">On</option>
268
267
  <option value="auto" data-i18n="scsAutoOption">Auto</option>
268
+ <option value="on" data-i18n="scsOnOption">On</option>
269
269
  <option value="off" data-i18n="scsOffOption">Off</option>
270
270
  </select>
271
271
  </label>
@@ -60,7 +60,8 @@ npm run smoke:model-roles
60
60
  node scripts/smoke-skills.js
61
61
  node scripts/smoke-dynamic-step-budget.js
62
62
  node scripts/smoke-coding-tools.js
63
- rg -n --hidden --glob '!node_modules/**' --glob '!.git/**' --glob '!dist/**' --glob '!coverage/**' 'xiaoyunque|小云雀|xyq|jianying|LALACHAN|啦啦|拉拉|阿芽|飒飒|Seedance|沉浸式短片|Trio\.png|display\.png|R1\.jpg|patchwork-leather|duanpian' .
63
+ rg -n --hidden --glob '!node_modules/**' --glob '!.git/**' --glob '!dist/**' --glob '!coverage/**' '<private-project-term-pattern>' .
64
64
  ```
65
65
 
66
- Result: checks passed, and the repository search found no remaining private workflow terms in AgInTiFlow runtime code, tests, or general references after excluding this audit's own search expression.
66
+ Result: checks passed, and the repository search found no remaining private
67
+ workflow terms in AgInTiFlow runtime code, tests, or general references.
@@ -6,6 +6,18 @@ This note records the working publication route for AgInTiFlow so future release
6
6
 
7
7
  ## Published Evidence
8
8
 
9
+ Latest verified release:
10
+
11
+ - Version: `0.20.182`
12
+ - Commit: `b5492f7`
13
+ - GitHub Actions run: `https://github.com/lazyingart/AgInTiFlow/actions/runs/26198123298`
14
+ - Workflow result: success
15
+ - npm registry check: `npm view @lazyingart/agintiflow version` returned `0.20.182`
16
+ - Installed verification: `npm install -g @lazyingart/agintiflow@0.20.182` then `aginti --version` returned `0.20.182`
17
+ - Webapp verification: `aginti webapp restart --port 3210` then `curl -fsS http://127.0.0.1:3210/health` returned `version":"0.20.182"` from the global npm package path.
18
+
19
+ Previous reference release:
20
+
9
21
  - Package: `@lazyingart/agintiflow`
10
22
  - Version: `0.20.169`
11
23
  - Commit: `6ef3768`
@@ -1,7 +1,7 @@
1
1
  # Bilingual Book Supervision Lessons
2
2
 
3
- This note records lessons from supervising AgInTiFlow on the ZhJpBook bilingual
4
- interlinear book pipeline. The goal is not to make AgInTiFlow a book-specific
3
+ This note records lessons from supervising AgInTiFlow on a multilingual
4
+ annotated book pipeline. The goal is not to make AgInTiFlow a book-specific
5
5
  tool. The goal is to identify which failures were project workflow issues and
6
6
  which reusable capabilities AgInTiFlow needs in order to complete large artifact
7
7
  projects from raw inputs to final outputs with less external guidance.
@@ -19,25 +19,25 @@ Observed AgInTiFlow primitives:
19
19
  - `docs/self-healing-pipelines.md`
20
20
  - `docs/auxiliary-image-generation.md`
21
21
 
22
- Observed ZhJpBook workflow pieces:
22
+ Observed project-local workflow pieces:
23
23
 
24
- - `scripts/interlinear/aginti_write_chunks.py`
25
- - `scripts/interlinear/aginti_dynamic_review_chunks.py`
26
- - `scripts/interlinear/start_aginti_parallel_json_writers.sh`
27
- - `scripts/interlinear/watch_aginti_compile.py`
28
- - `scripts/interlinear/compile_prepared_book_both_previews.sh`
24
+ - source ingestion and cleanup scripts
25
+ - chunk writer runners
26
+ - dynamic review scripts
27
+ - parallel structured-output workers
28
+ - compile and progress-watch scripts
29
29
 
30
- Observed Sishu run evidence:
30
+ Observed large-run evidence:
31
31
 
32
- - The book reached `2480/2480` manifest chunks valid with no missing chunks.
33
- - The final compile produced four PDFs: ZH-main and JP-main, color and
34
- blackwhite.
35
- - Page counts were `2387` for ZH-main and `2065` for JP-main.
32
+ - The book reached full manifest coverage with no missing chunks.
33
+ - The final compile produced multiple language, direction, and style variants.
34
+ - Page counts differed by output variant and had to be verified against the
35
+ current manifest.
36
36
  - A stale compile-watch status still reported older failed counts after the
37
37
  canonical progress report was clean, showing that multiple status snapshots
38
38
  can diverge unless one source of truth is enforced.
39
39
  - AgInTi image generation was useful for cover backgrounds, but exact title,
40
- author, furigana, and curation text still needed deterministic composition.
40
+ author, annotations, and curation text still needed deterministic composition.
41
41
 
42
42
  ## Main Finding
43
43
 
@@ -66,11 +66,12 @@ artifact-pipeline lifecycle that AgInTi can instantiate and supervise:
66
66
  These belong in the target repository or generated project scripts, not in
67
67
  AgInTiFlow core:
68
68
 
69
- - Book-specific source schemas and bilingual chunk schemas.
70
- - Chinese/Japanese rendering decisions, TeX macros, page size, grammar colors,
71
- ruby placement, table of contents, and cover typography.
72
- - Exact validators for source preservation, Hanzi tokenization, furigana/pinyin
73
- policy, grammar roles, and line-based interlinear layout.
69
+ - Book-specific source schemas and annotated chunk schemas.
70
+ - Language-pair rendering decisions, TeX or renderer macros, page size,
71
+ grammar colors, reading placement, table of contents, and cover typography.
72
+ - Exact validators for source preservation, script-specific tokenization,
73
+ reading or romanization policy, grammar roles, and line-based interlinear
74
+ layout.
74
75
  - Book plans, source bundles, source-specific OCR cleanup rules, and known
75
76
  editions/translations.
76
77
  - The concrete writer prompt for one literary/classical task.
@@ -132,8 +133,8 @@ Recommended core behavior:
132
133
  ### 2. Restarting From Zero Destroyed Efficiency
133
134
 
134
135
  Large book work is valuable even when partial. The most expensive artifacts were
135
- translation/alignment/ruby/grammar chunks. Retuning chunk size or prompt
136
- instructions should not discard reviewed chunks.
136
+ translation, alignment, reading, and grammar chunks. Retuning chunk size or
137
+ prompt instructions should not discard reviewed chunks.
137
138
 
138
139
  Recommended core behavior:
139
140
 
@@ -164,7 +165,7 @@ Recommended core behavior:
164
165
 
165
166
  The deterministic reviewer fixed schema/render issues. The user also wanted
166
167
  review that notices OCR corruption, missing text, bad line alignment, all-one
167
- color grammar pages, kana-only Japanese, source drift, and repeated filler.
168
+ color grammar pages, wrong-script output, source drift, and repeated filler.
168
169
 
169
170
  Recommended core behavior:
170
171
 
@@ -177,8 +178,8 @@ Recommended core behavior:
177
178
 
178
179
  ### 5. OCR and Source Ingestion Were Underestimated
179
180
 
180
- For scanned Chinese books, bad OCR flowed into later high-cost annotation. The
181
- right place to catch this is before bilingual generation.
181
+ For scanned or OCR-heavy books, bad OCR flowed into later high-cost annotation.
182
+ The right place to catch this is before multilingual generation.
182
183
 
183
184
  Recommended core behavior:
184
185
 
@@ -201,7 +202,7 @@ Recommended core behavior:
201
202
 
202
203
  - Cover/poster workflows should default to "image model creates background;
203
204
  deterministic renderer adds exact text" when exact titles, author names, URLs,
204
- ruby, or branding are required.
205
+ reading marks, annotations, or branding are required.
205
206
  - The image-generation tool should save raw prompt/result metadata, but project
206
207
  scripts should own final typography.
207
208
 
@@ -65,11 +65,11 @@ Project-local skill produced from this direction:
65
65
 
66
66
  - `.aginti/skills/<project-browser-workflow>/SKILL.md` in the task repository
67
67
 
68
- ### ZhJpBook And AgInTiFlow Implementation Session
68
+ ### Multilingual Book Pipeline And AgInTiFlow Implementation Session
69
69
 
70
70
  - Session: `019e1f99-289e-7711-986a-d41047f5ed21`
71
- - Status context shown by Codex: `~/ProjectsLFS/ZhJpBook`
72
- - Primary task repo involved: `/home/lachlan/ProjectsLFS/ZhJpBook`
71
+ - Status context shown by Codex: a project-local multilingual book repository
72
+ - Primary task repo involved: project-local, outside AgInTiFlow core
73
73
  - AgInTiFlow implementation repo: `/home/lachlan/ProjectsLFS/Agent/AgInTiFlow`
74
74
  - Role: implementation and validation session.
75
75
 
@@ -129,9 +129,9 @@ These sessions should be read together:
129
129
  owner.
130
130
  - The browser workflow session supplies the concrete failure mode: browser automation and media tasks
131
131
  can look successful while the visible external state is wrong or unverified.
132
- - ZhJpBook supplies the long-running pipeline pressure: the agent must keep
133
- moving through scripts, monitors, validators, and artifacts without accepting
134
- unsupported finish claims.
132
+ - The multilingual book pipeline supplies the long-running pipeline pressure:
133
+ the agent must keep moving through scripts, monitors, validators, and
134
+ artifacts without accepting unsupported finish claims.
135
135
  - AAPS supplies the project/workflow/block/program front-end contract where
136
136
  AgInTiFlow may act as a backend adapter but must not mutate AAPS scope or
137
137
  semantics unexpectedly.
@@ -1,6 +1,6 @@
1
1
  # Dynamic Step Budget And SCS Auto Routing
2
2
 
3
- This note documents the implemented design for dynamic `maxSteps` extension and SCS routing. SCS now defaults to `on`; auto routing remains available with `--scs auto` or `/scs auto` when a user wants SCS only for complex turns.
3
+ This note documents the implemented design for dynamic `maxSteps` extension and SCS routing. SCS defaults to `auto`: simple turns use the fast route, moderate work can use the main model without heavy validation, and high-risk evidence-bearing work activates the Student-Committee-Supervisor gates.
4
4
 
5
5
  ## Current State
6
6
 
@@ -15,11 +15,11 @@ Relevant paths:
15
15
  - `src/step-budget-controller.js`: owns deterministic progress/blocker checks, caps, serialization, and extension application.
16
16
  - `src/scs-controller.js`: supports `off`, `on`, `auto`, and the SCS student step-budget gate.
17
17
 
18
- SCS auto is supported but is not the default:
18
+ SCS auto is the default:
19
19
 
20
20
  - CLI: `--scs auto`.
21
21
  - Interactive: `/scs auto`.
22
- - Config: `enableScs: "on"` by default, or `"auto"` when explicitly requested.
22
+ - Config: `enableScs: "auto"` by default, or `"on"`/`"off"` when explicitly requested.
23
23
  - Router policy: `shouldActivateScs("auto", { goal, taskProfile, complexityScore })`.
24
24
  - Active model policy: when SCS is active, committee/student/supervisor use the main model.
25
25
 
@@ -86,11 +86,11 @@ SCS mode allows a slightly larger budget because the student gate is stricter:
86
86
 
87
87
  ### SCS Auto Mode
88
88
 
89
- `/scs auto` means the router may activate SCS for a specific turn. Signals include:
89
+ `/scs auto` means the router may activate SCS for a specific turn. It deliberately has a higher bar than smart model routing, so a turn can use the main model without paying SCS overhead. Signals include:
90
90
 
91
- - high smart-routing complexity score;
92
- - high-friction profiles such as Android, app, code, large-codebase, GitHub, maintenance, QA, research, review, security, supervision, or website;
93
- - prompt language such as debug, failing, migration, emulator, deploy, PDF, refactor, monitor, or long-running.
91
+ - very high smart-routing complexity score;
92
+ - high-friction profiles such as Android, app, large-codebase, GitHub, maintenance, QA, security, supervision, pipeline, or website;
93
+ - prompt language such as failing tests, fix the build, migration, deploy, browser automation, upload, PDF compilation, publish, monitor, or long-running.
94
94
 
95
95
  If SCS auto activates, dynamic step extension uses the SCS student gate. If SCS auto does not activate, dynamic step extension uses the normal deterministic gate.
96
96
 
@@ -212,7 +212,7 @@ Defaults:
212
212
  Routing semantics:
213
213
 
214
214
  - `/scs off`: never use SCS; dynamic budget uses normal deterministic monitoring if enabled.
215
- - `/scs on`: always use SCS; this is the default, and dynamic budget uses the student budget gate.
215
+ - `/scs on`: always use SCS, and dynamic budget uses the student budget gate.
216
216
  - `/scs auto`: router decides per run; if activated, dynamic budget uses the student gate.
217
217
 
218
218
  For observability, state preserves:
@@ -187,7 +187,7 @@ Recommended modes:
187
187
  | --- | --- |
188
188
  | `off` | Current behavior. |
189
189
  | `on` | SCS gates all non-trivial work in the session. |
190
- | `auto` | SCS only activates for complex tasks, write actions, multi-step shell work, GitHub, system maintenance, Android/iOS, LaTeX/PDF, and long-running tasks. |
190
+ | `auto` | Default. Simple turns stay linear, moderate tasks may use the main model without SCS, and SCS activates for high-risk/evidence-heavy work such as failing builds, repo-wide edits, GitHub/release work, browser uploads, system maintenance, Android/iOS, LaTeX/PDF compilation, and long-running supervision. |
191
191
 
192
192
  `/scs` should toggle SCS on/off in interactive CLI. `/scs auto` keeps the mature complex-task gate for users who want quality control without paying the SCS cost on simple turns.
193
193
 
@@ -795,12 +795,12 @@ try {
795
795
  throw new Error("interactive /review did not launch the bounded review workflow");
796
796
  }
797
797
  const scsDefaultStatusResult = await runChat("/scs status\n");
798
- if (!scsDefaultStatusResult.stdout.includes("SCS mode: on")) {
799
- throw new Error("interactive /scs status did not show default on mode");
798
+ if (!scsDefaultStatusResult.stdout.includes("SCS mode: auto")) {
799
+ throw new Error("interactive /scs status did not show default auto mode");
800
800
  }
801
801
  const statusFooterResult = await runChat("/status\n");
802
802
  if (
803
- !statusFooterResult.stdout.includes(`cwd=${tempRoot} scs=on aaps=off venice=off`) ||
803
+ !statusFooterResult.stdout.includes(`cwd=${tempRoot} scs=auto aaps=off venice=off`) ||
804
804
  !statusFooterResult.stdout.includes("permission=")
805
805
  ) {
806
806
  throw new Error("interactive /status did not include scs/aaps/venice mode state on the cwd line");
@@ -218,7 +218,8 @@ try {
218
218
  sessionId: "dynamic-step-budget-smoke",
219
219
  }
220
220
  );
221
- assert(config.enableScs === "on", "runtime config should default SCS mode to on");
221
+ assert(config.enableScs === "auto", "runtime config should default SCS mode to auto");
222
+ assert(config.scsActive === false, "simple mock write should not activate SCS in auto mode");
222
223
  const run = await runAgent(config);
223
224
  assert(!run.stopped, "mock run stopped instead of using dynamic extension");
224
225
  const written = await fs.readFile(path.join(workspace, "notes/dynamic-budget.md"), "utf8");
@@ -16,9 +16,11 @@ import {
16
16
  buildSupervisorInstruction,
17
17
  deterministicPlanActionContradiction,
18
18
  reviewScsFinish,
19
+ shouldActivateScs,
19
20
  shouldRequestScsReplan,
20
21
  } from "../src/scs-controller.js";
21
22
  import { buildScsEvidenceLedger, deriveScsTaskContract, evaluateScsEvidence } from "../src/scs-evidence.js";
23
+ import { resolveRuntimeConfig } from "../src/config.js";
22
24
 
23
25
  const repoRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
24
26
 
@@ -116,6 +118,86 @@ const fastRoute = selectModelRoute({
116
118
  });
117
119
  assert(fastRoute.model === "deepseek-v4-flash", "fast route did not use route model override");
118
120
 
121
+ const simpleSmartRoute = selectModelRoute({
122
+ routingMode: "smart",
123
+ provider: "deepseek",
124
+ goal: "say hello",
125
+ taskProfile: "auto",
126
+ });
127
+ assert(simpleSmartRoute.model === "deepseek-v4-flash", "simple smart route should use the route model");
128
+ assert(
129
+ !shouldActivateScs("auto", {
130
+ goal: "say hello",
131
+ taskProfile: "auto",
132
+ complexityScore: simpleSmartRoute.complexityScore,
133
+ }),
134
+ "SCS auto should stay inactive for simple turns"
135
+ );
136
+
137
+ const moderateSmartRoute = selectModelRoute({
138
+ routingMode: "smart",
139
+ provider: "deepseek",
140
+ goal: "implement a focused refactor design for one module",
141
+ taskProfile: "auto",
142
+ });
143
+ assert(moderateSmartRoute.model === "deepseek-v4-pro", "moderate smart route should use the main model");
144
+ assert(
145
+ !shouldActivateScs("auto", {
146
+ goal: "implement a focused refactor design for one module",
147
+ taskProfile: "auto",
148
+ complexityScore: moderateSmartRoute.complexityScore,
149
+ }),
150
+ "SCS auto should not gate every main-model turn"
151
+ );
152
+
153
+ const highRiskSmartRoute = selectModelRoute({
154
+ routingMode: "smart",
155
+ provider: "deepseek",
156
+ goal: "debug failing tests and fix the build in a large repo, then commit and push",
157
+ taskProfile: "auto",
158
+ });
159
+ assert(highRiskSmartRoute.model === "deepseek-v4-pro", "high-risk smart route should use the main model");
160
+ assert(
161
+ shouldActivateScs("auto", {
162
+ goal: "debug failing tests and fix the build in a large repo, then commit and push",
163
+ taskProfile: "auto",
164
+ complexityScore: highRiskSmartRoute.complexityScore,
165
+ }),
166
+ "SCS auto should activate for high-risk evidence-bearing work"
167
+ );
168
+ assert(
169
+ !shouldActivateScs("auto", { goal: "explain this function", taskProfile: "code", complexityScore: 0 }),
170
+ "code profile alone should not force SCS auto"
171
+ );
172
+
173
+ const simpleRuntimeConfig = resolveRuntimeConfig({
174
+ goal: "say hello",
175
+ provider: "deepseek",
176
+ routingMode: "smart",
177
+ taskProfile: "auto",
178
+ });
179
+ assert(simpleRuntimeConfig.enableScs === "auto", "runtime config should default SCS mode to auto");
180
+ assert(simpleRuntimeConfig.scsActive === false, "simple runtime config should not activate SCS");
181
+ assert(simpleRuntimeConfig.model === "deepseek-v4-flash", "simple runtime config should use route model");
182
+
183
+ const moderateRuntimeConfig = resolveRuntimeConfig({
184
+ goal: "implement a focused refactor design for one module",
185
+ provider: "deepseek",
186
+ routingMode: "smart",
187
+ taskProfile: "auto",
188
+ });
189
+ assert(moderateRuntimeConfig.scsActive === false, "moderate main-model work should not automatically activate SCS");
190
+ assert(moderateRuntimeConfig.model === "deepseek-v4-pro", "moderate runtime config should use main model");
191
+
192
+ const highRiskRuntimeConfig = resolveRuntimeConfig({
193
+ goal: "debug failing tests and fix the build in a large repo, then commit and push",
194
+ provider: "deepseek",
195
+ routingMode: "smart",
196
+ taskProfile: "auto",
197
+ });
198
+ assert(highRiskRuntimeConfig.scsActive === true, "high-risk runtime config should activate SCS");
199
+ assert(highRiskRuntimeConfig.model === "deepseek-v4-pro", "SCS runtime config should use main model");
200
+
119
201
  assert(MODEL_PROVIDER_GROUPS["venice-gpt"].provider === "venice", "venice-gpt group missing");
120
202
  assert(modelsForProviderGroup("venice").some((item) => item.id === "venice-uncensored-1-2"), "venice group missing Venice 1.2");
121
203
  assert(modelsForProviderGroup("venice-gemma").some((item) => item.id === "google-gemma-4-31b-it"), "venice-gemma bucket missing Gemma 4 instruct");
@@ -117,7 +117,7 @@ try {
117
117
  if (config.preferences?.packageInstallPolicy !== "allow") throw new Error("web did not default to Docker package installs");
118
118
  if (config.preferences?.permissionMode !== "normal") throw new Error("web did not default to normal permission mode");
119
119
  if (config.preferences?.workspaceWritePolicy !== "allow") throw new Error("web did not default to workspace writes allowed");
120
- if (config.preferences?.enableScs !== "on") throw new Error("web did not default to CLI-aligned SCS on mode");
120
+ if (config.preferences?.enableScs !== "auto") throw new Error("web did not default to CLI-aligned SCS auto mode");
121
121
  if (config.preferences?.dynamicSteps !== "auto") throw new Error("web did not default to CLI-aligned dynamic steps auto mode");
122
122
  if (config.preferences?.veniceMode !== false) throw new Error("web should default Venice shortcut mode off");
123
123
  if (Number(config.preferences?.maxSteps) < 24) throw new Error("web default max steps is too low");
@@ -9,11 +9,11 @@ triggers:
9
9
  - paired language
10
10
  - annotated book
11
11
  - parallel text
12
- - ruby
13
- - furigana
14
- - pinyin
15
- - xelatex
16
- - pocket book
12
+ - aligned annotations
13
+ - glossed text
14
+ - reading annotations
15
+ - translation notes
16
+ - source commentary
17
17
  tools:
18
18
  - read_file
19
19
  - write_file
@@ -46,7 +46,7 @@ This is a general workflow skill. It must not hard-code a specific book, languag
46
46
  Keep annotation policies project-defined:
47
47
 
48
48
  - Token shape, reading placement, grammar tags, and alignment granularity must come from the project schema.
49
- - For scripts that need per-character readings, validators should enforce that locally instead of relying on a prompt.
49
+ - For scripts that need per-token or per-character readings, validators should enforce that locally instead of relying on a prompt.
50
50
  - Placeholder translations, empty commentary, duplicated readings, copied modern paraphrases, or source drift should be detected by validators or reviewers.
51
51
  - Translation/reference quality gates must be derived from the project schema, language profile, and source audit. Do not bake one book's vocabulary, source names, or forbidden-token list into this built-in skill or AgInTiFlow core.
52
52
  - If a reference is unreliable for the requested target language, do not feed it to the writer as trusted translation. Either omit it, label it clearly as alignment/source-only context, or ask the project to supply a reliable reference.
@@ -43,6 +43,7 @@ import { isMcpBridgeTool } from "./mcp/policy.js";
43
43
  import { executeMcpBridgeTool } from "./mcp/tool-bridge.js";
44
44
  import { longJobStatus, startLongJob } from "./long-job-tools.js";
45
45
  import {
46
+ DEFAULT_SCS_MODE,
46
47
  buildSupervisorInstruction,
47
48
  createScsPlan,
48
49
  createScsReplan,
@@ -866,7 +867,7 @@ async function maybeExtendStepBudget({ client, config, state, store, observers,
866
867
  runtimeDecision,
867
868
  stepBudget: serializeStepBudgetState(stepBudget),
868
869
  });
869
- state.meta.scs = state.meta.scs || { enabled: true, mode: config.enableScs || "on", active: true };
870
+ state.meta.scs = state.meta.scs || { enabled: true, mode: config.enableScs || DEFAULT_SCS_MODE, active: true };
870
871
  state.meta.scs.budgetReviews = (state.meta.scs.budgetReviews || 0) + 1;
871
872
  state.meta.scs.lastStudentDecision = scsDecision;
872
873
  await store.appendEvent(`scs.student.${scsDecision.decision}`, {
@@ -969,7 +970,7 @@ async function requestScsReplan({ client, config, state, store, observers, decis
969
970
  if (!config.scsActive || !shouldRequestScsReplan(decision)) return null;
970
971
  state.meta.scs = state.meta.scs || {
971
972
  enabled: true,
972
- mode: config.enableScs || "on",
973
+ mode: config.enableScs || DEFAULT_SCS_MODE,
973
974
  active: true,
974
975
  model: `${config.provider}/${config.model}`,
975
976
  phase: 1,
@@ -2368,12 +2369,12 @@ export async function runAgent(config) {
2368
2369
  await store.appendEvent("scs.plan.requested", {
2369
2370
  provider: config.provider,
2370
2371
  model: config.model,
2371
- mode: config.enableScs || "on",
2372
+ mode: config.enableScs || DEFAULT_SCS_MODE,
2372
2373
  });
2373
2374
  observers.event("scs.plan.requested", {
2374
2375
  provider: config.provider,
2375
2376
  model: config.model,
2376
- mode: config.enableScs || "on",
2377
+ mode: config.enableScs || DEFAULT_SCS_MODE,
2377
2378
  });
2378
2379
  const scsPlan = await createScsPlan(client, config, state, {
2379
2380
  events: await store.loadEvents(),
@@ -2444,7 +2445,7 @@ export async function runAgent(config) {
2444
2445
  } else if (config.scsActive && !state.meta?.scs?.supervisorInstructionInjected) {
2445
2446
  state.meta.scs = state.meta.scs || {
2446
2447
  enabled: true,
2447
- mode: config.enableScs || "on",
2448
+ mode: config.enableScs || DEFAULT_SCS_MODE,
2448
2449
  active: true,
2449
2450
  model: `${config.provider}/${config.model}`,
2450
2451
  phase: 1,
@@ -2547,7 +2548,7 @@ export async function runAgent(config) {
2547
2548
  emitConsole(config, `Provider: ${config.provider}`, { kind: "meta" });
2548
2549
  emitConsole(config, `Model: ${config.model}`, { kind: "meta" });
2549
2550
  emitConsole(config, `Routing: ${config.routingMode} (${config.routeReason})`, { kind: "meta" });
2550
- if (config.scsActive) emitConsole(config, `SCS: ${config.enableScs || "on"} using main-model policy`, { kind: "meta" });
2551
+ if (config.scsActive) emitConsole(config, `SCS: ${config.enableScs || DEFAULT_SCS_MODE} using main-model policy`, { kind: "meta" });
2551
2552
  emitConsole(config, `Workspace: ${config.commandCwd}`, { kind: "meta" });
2552
2553
  emitConsole(config, `Sessions: ${config.sessionsDir}`, { kind: "meta" });
2553
2554
  if (config.projectSessionsDir) emitConsole(config, `Project session index: ${config.projectSessionsDir}`, { kind: "meta" });
@@ -2731,7 +2732,7 @@ export async function runAgent(config) {
2731
2732
  taskProfile: config.taskProfile,
2732
2733
  goal: config.goal,
2733
2734
  });
2734
- state.meta.scs = state.meta.scs || { enabled: true, mode: config.enableScs || "on", active: true };
2735
+ state.meta.scs = state.meta.scs || { enabled: true, mode: config.enableScs || DEFAULT_SCS_MODE, active: true };
2735
2736
  state.meta.scs.lastStudentDecision = decision;
2736
2737
  await store.appendEvent(`scs.student.${decision.decision}`, decision);
2737
2738
  observers.event(`scs.student.${decision.decision}`, {
@@ -2860,7 +2861,7 @@ export async function runAgent(config) {
2860
2861
  taskProfile: config.taskProfile,
2861
2862
  goal: config.goal,
2862
2863
  });
2863
- state.meta.scs = state.meta.scs || { enabled: true, mode: config.enableScs || "on", active: true };
2864
+ state.meta.scs = state.meta.scs || { enabled: true, mode: config.enableScs || DEFAULT_SCS_MODE, active: true };
2864
2865
  state.meta.scs.lastStudentDecision = decision;
2865
2866
  await store.appendEvent(`scs.student.${decision.decision}`, decision);
2866
2867
  observers.event(`scs.student.${decision.decision}`, {
@@ -2940,7 +2941,7 @@ export async function runAgent(config) {
2940
2941
  taskProfile: config.taskProfile,
2941
2942
  goal: config.goal,
2942
2943
  });
2943
- state.meta.scs = state.meta.scs || { enabled: true, mode: config.enableScs || "on", active: true };
2944
+ state.meta.scs = state.meta.scs || { enabled: true, mode: config.enableScs || DEFAULT_SCS_MODE, active: true };
2944
2945
  state.meta.scs.monitorReviews = (state.meta.scs.monitorReviews || 0) + 1;
2945
2946
  state.meta.scs.lastStudentDecision = decision;
2946
2947
  await store.appendEvent(`scs.student.${decision.decision}`, {
@@ -2992,7 +2993,7 @@ export async function runAgent(config) {
2992
2993
  taskProfile: config.taskProfile,
2993
2994
  goal: config.goal,
2994
2995
  });
2995
- state.meta.scs = state.meta.scs || { enabled: true, mode: config.enableScs || "on", active: true };
2996
+ state.meta.scs = state.meta.scs || { enabled: true, mode: config.enableScs || DEFAULT_SCS_MODE, active: true };
2996
2997
  state.meta.scs.monitorReviews = (state.meta.scs.monitorReviews || 0) + 1;
2997
2998
  state.meta.scs.lastStudentDecision = decision;
2998
2999
  await store.appendEvent(`scs.student.${decision.decision}`, {
package/src/cli.js CHANGED
@@ -37,6 +37,7 @@ import { handleSkillMeshCommand } from "./skillmesh.js";
37
37
  import { handleAapsCliCommand } from "./aaps-adapter.js";
38
38
  import { formatInstructionTemplateList, normalizeInstructionTemplate } from "./behavior-contract.js";
39
39
  import { applyPermissionMode, normalizePermissionMode } from "./permission-modes.js";
40
+ import { DEFAULT_SCS_MODE } from "./scs-controller.js";
40
41
  import { ensureAgintiWebApp, readWebAppPreference, stopAgintiWebApp, writeWebAppPreference } from "./web-autostart.js";
41
42
  import { dockerHostInstallPlan, formatDockerSetupText, summarizeDockerSetup } from "./docker-setup.js";
42
43
  import { mcpCliCommand, formatMcpCliResult } from "./mcp/tool-bridge.js";
@@ -984,7 +985,7 @@ function agentDefaults(args) {
984
985
  allowWebSearch: args.allowWebSearch ?? true,
985
986
  allowMcpTools: args.allowMcpTools ?? true,
986
987
  allowParallelScouts: args.allowParallelScouts ?? true,
987
- enableScs: args.enableScs || process.env.AGINTI_SCS_MODE || "on",
988
+ enableScs: args.enableScs || process.env.AGINTI_SCS_MODE || DEFAULT_SCS_MODE,
988
989
  parallelScoutCount: args.parallelScoutCount || (Number.isFinite(envScoutCount) && envScoutCount > 0 ? envScoutCount : 3),
989
990
  sandboxMode: args.sandboxMode || envSandboxMode || permissionDefaults.sandboxMode || "docker-workspace",
990
991
  packageInstallPolicy: args.packageInstallPolicy || envPackageInstallPolicy || permissionDefaults.packageInstallPolicy || "allow",
package/src/config.js CHANGED
@@ -7,7 +7,7 @@ import { loadProjectEnv, projectPaths, resolveProjectRoot } from "./project.js";
7
7
  import { normalizeTaskProfile } from "./task-profiles.js";
8
8
  import { recommendedMaxStepsForTask } from "./engineering-guidance.js";
9
9
  import { resolveLanguage } from "./i18n.js";
10
- import { normalizeScsMode, shouldActivateScs } from "./scs-controller.js";
10
+ import { DEFAULT_SCS_MODE, normalizeScsMode, shouldActivateScs } from "./scs-controller.js";
11
11
  import { applyPermissionMode, normalizePermissionMode } from "./permission-modes.js";
12
12
  import { normalizeDynamicStepsMode } from "./step-budget-controller.js";
13
13
 
@@ -78,7 +78,7 @@ export function resolveRuntimeConfig(args, overrides = {}) {
78
78
  auxiliaryModel: overrides.auxiliaryModel || args.auxiliaryModel || process.env.AGINTI_AUX_MODEL || "",
79
79
  });
80
80
 
81
- const scsMode = normalizeScsMode(overrides.enableScs ?? args.enableScs ?? process.env.AGINTI_SCS_MODE ?? "on");
81
+ const scsMode = normalizeScsMode(overrides.enableScs ?? args.enableScs ?? process.env.AGINTI_SCS_MODE ?? DEFAULT_SCS_MODE);
82
82
  const scsActive = shouldActivateScs(scsMode, {
83
83
  goal: args.goal || "",
84
84
  taskProfile,
@@ -35,7 +35,7 @@ import {
35
35
  setSkillMeshMode,
36
36
  skillMeshModeChoices,
37
37
  } from "./skillmesh.js";
38
- import { normalizeScsMode } from "./scs-controller.js";
38
+ import { DEFAULT_SCS_MODE, normalizeScsMode } from "./scs-controller.js";
39
39
  import { formatAapsResult, runAapsAction } from "./aaps-adapter.js";
40
40
  import { formatInstructionTemplateList, normalizeInstructionTemplate } from "./behavior-contract.js";
41
41
  import {
@@ -2658,7 +2658,7 @@ function createState(args = {}) {
2658
2658
  allowWebSearch: args.allowWebSearch ?? true,
2659
2659
  allowMcpTools: args.allowMcpTools ?? true,
2660
2660
  allowParallelScouts: args.allowParallelScouts ?? true,
2661
- enableScs: normalizeScsMode(args.enableScs || process.env.AGINTI_SCS_MODE || "on"),
2661
+ enableScs: normalizeScsMode(args.enableScs || process.env.AGINTI_SCS_MODE || DEFAULT_SCS_MODE),
2662
2662
  parallelScoutCount: args.parallelScoutCount || 3,
2663
2663
  allowWrapperTools: args.allowWrapperTools ?? isWrapperAvailable(args.preferredWrapper || "codex"),
2664
2664
  allowDestructive: args.allowDestructive ?? permissionDefaults.allowDestructive ?? false,
@@ -14,40 +14,38 @@ import {
14
14
  } from "./scs-evidence.js";
15
15
 
16
16
  export const SCS_MODES = ["off", "on", "auto"];
17
+ export const DEFAULT_SCS_MODE = "auto";
17
18
 
18
- const COMPLEX_AUTO_PROFILES = new Set([
19
+ const SCS_AUTO_PROFILES = new Set([
19
20
  "android",
20
21
  "app",
21
- "book",
22
- "code",
23
22
  "codebase",
24
23
  "database",
25
24
  "devops",
26
25
  "github",
27
26
  "ios",
28
27
  "large-codebase",
29
- "latex",
30
28
  "maintenance",
31
- "novel",
32
- "paper",
29
+ "pipeline",
33
30
  "qa",
34
- "research",
35
- "review",
36
31
  "security",
37
32
  "supervision",
38
33
  "website",
39
- "writing",
40
34
  ]);
41
35
 
42
- const COMPLEX_AUTO_HINTS = [
43
- /\b(complex|complicated|large|multi[- ]file|cross[- ]file|repo[- ]wide|workspace[- ]wide)\b/i,
44
- /\b(implement|refactor|debug|failing|regression|root cause|test|build|compile|migrate)\b/i,
45
- /\b(android|ios|gradle|xcode|docker|systemd|github|pull request|release|deploy|latex|pdf)\b/i,
46
- /\b(supervise|monitor|long[- ]running|resume|tmux|simulator|emulator)\b/i,
36
+ const SCS_AUTO_HINTS = [
37
+ /\b(large|big|complex|complicated)\s+(repo|repository|codebase|project|task|migration|refactor)\b/i,
38
+ /\b(multi[- ]file|cross[- ]file|repo[- ]wide|workspace[- ]wide)\b/i,
39
+ /\b(root cause|regression|failing tests?|fix the build|make it pass|self[- ]debug|test[- ]debug[- ]validate|tdv)\b/i,
40
+ /\b(release|publish|deploy|migration|database migration|schema migration|production|rollback|ci|github|pull request)\b/i,
41
+ /\b(android|ios|gradle|xcode|docker|systemd|kubernetes|nginx|postgres|redis|toolchain|permission denied)\b/i,
42
+ /\b(supervise|monitor|long[- ]running|background|resume|tmux|simulator|emulator|pipeline|watchdog)\b/i,
47
43
  /\b(browser|web[- ]?ui|website|chrome|chromedriver|cdp|devtools|playwright|selenium|puppeteer)\b/i,
48
- /\b(upload|attach|asset library|submit|publish|poll|download|reference video|reference image)\b/i,
49
- /\b(novel|book|chapter|manuscript|screenplay|story bible|long[- ]form|research paper)\b/i,
50
- /浏览器|网页|上传|提交|发布|素材库|资产库|参考图|参考视频|按钮|登录|验证码|积分/,
44
+ /\b(upload|attach|asset library|submit|poll|download|reference video|reference image|visual evidence)\b/i,
45
+ /\b(latex|pdflatex|latexmk|compile)\b.{0,80}\b(pdf|paper|manuscript|report)\b/i,
46
+ /\b(write|create|generate|produce)\b.{0,80}\b(pdf|compiled artifact|zip|dataset|database|csv|json|figure|plot|report)\b/i,
47
+ /\b(commit|push|npm publish|trusted publishing|release workflow|install globally)\b/i,
48
+ /浏览器|网页|上传|提交|发布|素材库|资产库|参考图|参考视频|按钮|登录|验证码|积分|编译|部署|回滚/,
51
49
  ];
52
50
 
53
51
  function compact(value = "", limit = 1200) {
@@ -181,9 +179,9 @@ export function shouldActivateScs(mode = "off", context = {}) {
181
179
 
182
180
  const profile = String(context.taskProfile || "").toLowerCase();
183
181
  const goal = String(context.goal || "");
184
- if (Number(context.complexityScore || 0) >= 3) return true;
185
- if (COMPLEX_AUTO_PROFILES.has(profile)) return true;
186
- return COMPLEX_AUTO_HINTS.some((hint) => hint.test(goal));
182
+ if (SCS_AUTO_PROFILES.has(profile)) return true;
183
+ if (SCS_AUTO_HINTS.some((hint) => hint.test(goal))) return true;
184
+ return Number(context.complexityScore || 0) >= 5;
187
185
  }
188
186
 
189
187
  function fallbackPlan(goal = "") {
@@ -738,7 +736,7 @@ async function createScsPhase(client, config, state, context = {}, options = {})
738
736
 
739
737
  const scs = {
740
738
  enabled: true,
741
- mode: config.enableScs || "on",
739
+ mode: config.enableScs || DEFAULT_SCS_MODE,
742
740
  active: true,
743
741
  model: `${config.provider}/${config.model}`,
744
742
  phase,
package/src/web-db.js CHANGED
@@ -6,8 +6,9 @@ import { projectPaths } from "./project.js";
6
6
  import { deleteSessionIndex, renameSessionIndex, upsertSessionIndex } from "./session-index.js";
7
7
  import { loadDatabaseSync } from "./sqlite.js";
8
8
  import { permissionModeDefaults } from "./permission-modes.js";
9
+ import { DEFAULT_SCS_MODE } from "./scs-controller.js";
9
10
 
10
- const PREFERENCES_SCHEMA_VERSION = 10;
11
+ const PREFERENCES_SCHEMA_VERSION = 11;
11
12
 
12
13
  function jsonStatePath(dbPath) {
13
14
  return dbPath.replace(/\.sqlite$/i, ".json");
@@ -71,7 +72,7 @@ function defaultPreferences(baseDir) {
71
72
  allowAuxiliaryTools: true,
72
73
  allowWebSearch: true,
73
74
  allowParallelScouts: true,
74
- enableScs: process.env.AGINTI_SCS_MODE || "on",
75
+ enableScs: process.env.AGINTI_SCS_MODE || DEFAULT_SCS_MODE,
75
76
  dynamicSteps: process.env.AGINTI_DYNAMIC_STEPS || "auto",
76
77
  veniceMode: false,
77
78
  parallelScoutCount: 3,
@@ -226,7 +227,7 @@ export class WebDatabase {
226
227
  preferences.allowOutsideWorkspaceFileTools = permissions.allowOutsideWorkspaceFileTools;
227
228
  }
228
229
  if ((parsed.preferencesSchemaVersion || 1) < 9) {
229
- preferences.enableScs = preferences.enableScs || process.env.AGINTI_SCS_MODE || "on";
230
+ preferences.enableScs = preferences.enableScs || process.env.AGINTI_SCS_MODE || DEFAULT_SCS_MODE;
230
231
  preferences.dynamicSteps = preferences.dynamicSteps || process.env.AGINTI_DYNAMIC_STEPS || "auto";
231
232
  }
232
233
  if ((parsed.preferencesSchemaVersion || 1) < 10) {
@@ -243,6 +244,9 @@ export class WebDatabase {
243
244
  preferences.mainModel = "deepseek-v4-pro";
244
245
  }
245
246
  }
247
+ if ((parsed.preferencesSchemaVersion || 1) < 11 && !process.env.AGINTI_SCS_MODE && (parsed.enableScs || preferences.enableScs) === "on") {
248
+ preferences.enableScs = DEFAULT_SCS_MODE;
249
+ }
246
250
  this.savePreferences(preferences);
247
251
  }
248
252
  if (
package/web.js CHANGED
@@ -27,7 +27,7 @@ import {
27
27
  normalizePermissionMode,
28
28
  permissionModeForApprovalCategory,
29
29
  } from "./src/permission-modes.js";
30
- import { normalizeScsMode } from "./src/scs-controller.js";
30
+ import { DEFAULT_SCS_MODE, normalizeScsMode } from "./src/scs-controller.js";
31
31
  import { normalizeDynamicStepsMode } from "./src/step-budget-controller.js";
32
32
  import {
33
33
  ensureProjectSessionStorage,
@@ -566,7 +566,7 @@ function normalizePreferencePayload(body = {}, current = db.getPreferences()) {
566
566
  typeof body.allowMcpTools === "boolean" ? body.allowMcpTools : current.allowMcpTools !== false,
567
567
  allowParallelScouts:
568
568
  typeof body.allowParallelScouts === "boolean" ? body.allowParallelScouts : current.allowParallelScouts !== false,
569
- enableScs: normalizeScsMode(body.enableScs || current.enableScs || process.env.AGINTI_SCS_MODE || "on"),
569
+ enableScs: normalizeScsMode(body.enableScs || current.enableScs || process.env.AGINTI_SCS_MODE || DEFAULT_SCS_MODE),
570
570
  dynamicSteps: normalizeDynamicStepsMode(body.dynamicSteps || current.dynamicSteps || process.env.AGINTI_DYNAMIC_STEPS || "auto"),
571
571
  veniceMode: typeof body.veniceMode === "boolean" ? body.veniceMode : current.veniceMode === true,
572
572
  parallelScoutCount: