@lazyingart/agintiflow 0.20.181 → 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` |
@@ -138,6 +138,22 @@ aginti "start a tmux session named demo, run ls in it, keep it open, and tell me
138
138
 
139
139
  The agent should use `tmux_start_session`, `tmux_send_keys`, and `tmux_capture_pane`, not Docker `run_command`. In Docker sandbox mode, tmux commands must stay inside the project. In host mode, tmux command text is still governed by host shell policy; if a tmux command is blocked, present the suggested rerun path instead of trying tmux as a workaround. For trusted whole-host tmux work, use the host recipe above.
140
140
 
141
+ Long download or long command:
142
+
143
+ ```bash
144
+ aginti "download this large zip with wget -c, verify the final byte count, and do not burn model steps polling it"
145
+ ```
146
+
147
+ The agent should use `start_long_job` once instead of repeatedly calling `wait`, `run_command`, or `tmux_capture_pane`. The tool creates `.aginti/long-jobs/<job-id>/status.json`, stdout/stderr logs, a supervisor log, and an optional status card. For resumable downloads, the agent should first determine `Content-Length` when practical, then call `start_long_job` with:
148
+
149
+ - `command`: a resumable transfer such as `wget -c URL -O file.zip`
150
+ - `expectedOutputPath`: the downloaded file
151
+ - `expectedSizeBytes`: the expected byte count
152
+ - `verifyCommand`: a deterministic check such as `unzip -t file.zip` or `sha256sum -c`
153
+ - `restartOnFailure`: `true` when the transfer command is safe to resume
154
+
155
+ After `start_long_job` succeeds, the model loop should finish with the job id and status path. Later status checks should use `long_job_status` or direct shell inspection of the status JSON. This keeps multi-hour I/O under a shell supervisor instead of consuming model tokens and step budget.
156
+
141
157
  ## Future Persistent Container Mode
142
158
 
143
159
  A useful next runtime mode is a service container:
@@ -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.181",
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",
@@ -63,6 +63,7 @@
63
63
  "scripts/smoke-capabilities.js",
64
64
  "scripts/smoke-auto-update.js",
65
65
  "scripts/smoke-inbox.js",
66
+ "scripts/smoke-long-jobs.js",
66
67
  "scripts/smoke-mcp.js",
67
68
  "scripts/fixtures/mcp-stdio-smoke-server.mjs",
68
69
  "scripts/smoke-model-roles.js",
@@ -106,6 +107,7 @@
106
107
  "smoke:skillmesh": "node scripts/smoke-skillmesh.js",
107
108
  "smoke:toolchain-docker": "node scripts/smoke-toolchain-docker.js",
108
109
  "smoke:inbox": "node scripts/smoke-inbox.js",
110
+ "smoke:long-jobs": "node scripts/smoke-long-jobs.js",
109
111
  "smoke:mcp": "node scripts/smoke-mcp.js",
110
112
  "smoke:model-roles": "node scripts/smoke-model-roles.js",
111
113
  "smoke:platform": "node scripts/smoke-platform.js",
@@ -125,7 +127,7 @@
125
127
  "storage:migrate": "node bin/aginti-cli.js storage migrate",
126
128
  "publish:env": "node scripts/npm-publish-from-env.js publish --access public",
127
129
  "publish:env:whoami": "node scripts/npm-publish-from-env.js whoami",
128
- "test": "npm run check && npm run smoke:runtime-compat && npm run smoke:autoupdate && npm run smoke:web-api && npm run smoke:web-ui && npm run smoke:web-autostart && npm run smoke:webapp-command && npm run smoke:web-port-fallback && npm run smoke:docker-command && npm run smoke:coding-tools && npm run smoke:dynamic-step-budget && npm run smoke:aaps-adapter && npm run smoke:auxiliary-tools && npm run smoke:perception-research && npm run smoke:auth && npm run smoke:canvas-artifacts && npm run smoke:capabilities && npm run smoke:mcp && npm run smoke:model-roles && npm run smoke:platform && npm run smoke:permission-modes && npm run smoke:skills && npm run smoke:skillmesh && npm run smoke:tmux-tools && npm run smoke:cli-chat && npm run smoke:inbox",
130
+ "test": "npm run check && npm run smoke:runtime-compat && npm run smoke:autoupdate && npm run smoke:web-api && npm run smoke:web-ui && npm run smoke:web-autostart && npm run smoke:webapp-command && npm run smoke:web-port-fallback && npm run smoke:docker-command && npm run smoke:coding-tools && npm run smoke:dynamic-step-budget && npm run smoke:aaps-adapter && npm run smoke:auxiliary-tools && npm run smoke:perception-research && npm run smoke:auth && npm run smoke:canvas-artifacts && npm run smoke:capabilities && npm run smoke:mcp && npm run smoke:model-roles && npm run smoke:platform && npm run smoke:permission-modes && npm run smoke:skills && npm run smoke:skillmesh && npm run smoke:tmux-tools && npm run smoke:long-jobs && npm run smoke:cli-chat && npm run smoke:inbox",
129
131
  "pack:dry-run": "npm pack --dry-run",
130
132
  "smoke:capabilities": "node scripts/smoke-capabilities.js"
131
133
  },
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");
@@ -0,0 +1,104 @@
1
+ #!/usr/bin/env node
2
+ import assert from "node:assert/strict";
3
+ import fs from "node:fs/promises";
4
+ import os from "node:os";
5
+ import path from "node:path";
6
+ import { checkToolUse } from "../src/guardrails.js";
7
+ import { longJobStatus, startLongJob } from "../src/long-job-tools.js";
8
+ import { tmuxAvailable } from "../src/tmux-tools.js";
9
+
10
+ const workspace = await fs.mkdtemp(path.join(os.tmpdir(), "agintiflow-long-job-"));
11
+ const config = {
12
+ allowShellTool: true,
13
+ allowDestructive: true,
14
+ allowPasswords: true,
15
+ commandCwd: workspace,
16
+ sandboxMode: "host",
17
+ useDockerSandbox: false,
18
+ };
19
+ const dockerConfig = {
20
+ ...config,
21
+ allowDestructive: false,
22
+ allowPasswords: false,
23
+ useDockerSandbox: true,
24
+ sandboxMode: "docker-workspace",
25
+ packageInstallPolicy: "allow",
26
+ };
27
+
28
+ function sleep(ms) {
29
+ return new Promise((resolve) => setTimeout(resolve, ms));
30
+ }
31
+
32
+ try {
33
+ if (!(await tmuxAvailable())) {
34
+ console.log(JSON.stringify({ ok: true, skipped: true, reason: "tmux is not installed" }, null, 2));
35
+ process.exit(0);
36
+ }
37
+
38
+ const noShell = checkToolUse({
39
+ toolName: "start_long_job",
40
+ args: { command: "printf ok > out.txt" },
41
+ config: { ...config, allowShellTool: false },
42
+ });
43
+ assert.equal(noShell.allowed, false, "start_long_job should require shell capability");
44
+
45
+ const outsidePath = path.join(os.tmpdir(), "aginti-long-job-outside.txt");
46
+ const outsideGuard = checkToolUse({
47
+ toolName: "start_long_job",
48
+ args: { name: "outside", command: `cat ${outsidePath}` },
49
+ config: dockerConfig,
50
+ });
51
+ assert.equal(outsideGuard.allowed, false, "Docker-mode long jobs should block outside host absolute paths");
52
+
53
+ const start = await startLongJob(
54
+ {
55
+ name: "smoke-download-style",
56
+ command: "printf 'abc123' > download.bin",
57
+ expectedOutputPath: "download.bin",
58
+ expectedSizeBytes: 6,
59
+ verifyCommand: "grep -q abc download.bin",
60
+ pollIntervalSeconds: 5,
61
+ note: "Smoke test for durable long command handoff.",
62
+ },
63
+ config
64
+ );
65
+ assert.equal(start.ok, true, start.error || start.reason);
66
+ assert.equal(start.background, true, "long job should return as a background handoff");
67
+ assert.match(start.statusPath, /^\.aginti\/long-jobs\//, "status path should be project-local");
68
+
69
+ let status = null;
70
+ for (let i = 0; i < 30; i += 1) {
71
+ await sleep(250);
72
+ status = await longJobStatus({ jobId: start.jobId }, config);
73
+ assert.equal(status.ok, true, status.reason);
74
+ if (["completed", "failed"].includes(status.state)) break;
75
+ }
76
+ assert.equal(status?.state, "completed", `long job did not complete: ${JSON.stringify(status)}`);
77
+ assert.equal(status.outputBytes, 6, "expected-size progress was not recorded");
78
+ assert.equal(status.verifyExitCode, 0, "verify command did not pass");
79
+
80
+ const output = await fs.readFile(path.join(workspace, "download.bin"), "utf8");
81
+ assert.equal(output, "abc123", "job output content mismatch");
82
+ await fs.access(path.join(workspace, start.statusPath));
83
+ await fs.access(path.join(workspace, start.stdoutPath));
84
+ await fs.access(path.join(workspace, start.stderrPath));
85
+ await fs.access(path.join(workspace, start.supervisorLogPath));
86
+
87
+ console.log(
88
+ JSON.stringify(
89
+ {
90
+ ok: true,
91
+ workspace,
92
+ jobId: start.jobId,
93
+ statusPath: start.statusPath,
94
+ state: status.state,
95
+ outputBytes: status.outputBytes,
96
+ verifyExitCode: status.verifyExitCode,
97
+ },
98
+ null,
99
+ 2
100
+ )
101
+ );
102
+ } finally {
103
+ await fs.rm(workspace, { recursive: true, force: true }).catch(() => {});
104
+ }
@@ -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.