@lazyingart/agintiflow 0.20.151 → 0.20.157

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.
@@ -31,7 +31,7 @@ SCS uses the selected main model for every internal role.
31
31
  | Role | Right | Boundary |
32
32
  | --- | --- | --- |
33
33
  | Committee | Draft one next-phase plan with acceptance criteria and stop conditions. | Cannot approve plans or call tools. |
34
- | Student | Approve/veto the phase plan, review failure evidence, and approve/reject finish. | Cannot call tools or override runtime safety. |
34
+ | Student | Act as the independent validator: approve/veto the phase plan, review failure evidence, and approve/reject finish. | Cannot call tools, approve its own work, or override runtime safety. |
35
35
  | Supervisor | Execute the approved phase with the existing browser, shell, file, canvas, and wrapper tools. | Cannot replace the strategic plan without student review. |
36
36
 
37
37
  The runtime remains the real authority for command policy, filesystem guardrails, secret redaction, session persistence, and user interruption.
@@ -44,9 +44,10 @@ When SCS is active:
44
44
  - Parallel scouts are disabled by default unless explicitly requested, avoiding duplicate advisory layers.
45
45
  - The normal `createPlan()` path is replaced by a committee draft plus student approval.
46
46
  - An approved supervisor instruction is injected into the execution loop.
47
- - Failed or blocked tools trigger a bounded student monitor review.
47
+ - Failed, blocked, suspicious, or mismatched tools trigger a bounded student validator review.
48
48
  - Every fourth execution step triggers a bounded progress review for long runs.
49
49
  - `finish` and assistant-content completion pass through a final student gate.
50
+ - If the student validator rejects progress or finish, the runtime asks the committee for a new phase plan and sends that plan back through the student gate before the supervisor continues.
50
51
  - Decisions are persisted as `scs.*` events and the phase pack is saved as a session artifact.
51
52
 
52
53
  The current implementation is deliberately bounded:
@@ -93,6 +94,10 @@ Avoid SCS for:
93
94
 
94
95
  SCS emits compact event names:
95
96
 
97
+ - `conversation.continued`
98
+ - `surgical_context.prepared`
99
+ - `surgical_context.failed`
100
+ - `scs.plan.requested`
96
101
  - `scs.enabled`
97
102
  - `scs.committee.plan_drafted`
98
103
  - `scs.student.approve_plan`
@@ -102,10 +107,13 @@ SCS emits compact event names:
102
107
  - `scs.student.reject_phase`
103
108
  - `scs.student.finish_allowed`
104
109
  - `scs.student.finish_rejected`
110
+ - `scs.committee.replan_drafted`
105
111
  - `scs.supervisor.phase_started`
106
112
 
107
113
  These are saved in the normal session event log under `~/.agintiflow/sessions/<session-id>/events.jsonl`, with project pointers under `.aginti-sessions/`.
108
114
 
115
+ Browser and CDP helper commands are reviewed by evidence, not only by exit status. If a click or selector command reports `ok: true` but returns broad whole-page text, repeated navigation/history/sidebar text, or no scoped target evidence, SCS treats the result as suspicious and asks the supervisor to verify state or switch to a precise selector before continuing.
116
+
109
117
  ## Design Reference
110
118
 
111
119
  The deeper design research lives in [references/student-committee-supervisor-mode.md](../references/student-committee-supervisor-mode.md). The important design choice is that SCS is a typed event gate, not a free-form debate. Internal roles emit structured decisions, and the runtime decides what those decisions are allowed to do.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lazyingart/agintiflow",
3
- "version": "0.20.151",
3
+ "version": "0.20.157",
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",
@@ -405,6 +405,16 @@ try {
405
405
  ) {
406
406
  throw new Error("terminal prompt layout did not render visual-only input padding safely");
407
407
  }
408
+ const footerPromptLayout = buildPromptLayout("hello", 5, 110, 24, {
409
+ commandCwd: "/tmp/aginti-project",
410
+ footerStatus: "scs=auto aaps=off venice=off",
411
+ });
412
+ const footerPromptText = footerPromptLayout.renderedRows
413
+ .map((line) => line.replace(/\x1b\[[0-9;?]*[ -/]*[@-~]/g, ""))
414
+ .join("\n");
415
+ if (!footerPromptText.includes("cwd /tmp/aginti-project scs=auto aaps=off venice=off")) {
416
+ throw new Error("terminal prompt layout did not render mode status after the cwd footer");
417
+ }
408
418
  const committedUserText = formatCommittedUserPromptLines("list files", 90)
409
419
  .map((line) => line.replace(/\x1b\[[0-9;?]*[ -/]*[@-~]/g, ""))
410
420
  .join("\n");
@@ -683,9 +693,20 @@ try {
683
693
  if (!reviewResult.stdout.includes("Review focus: changed files only") || !reviewResult.stdout.includes("Mock run complete")) {
684
694
  throw new Error("interactive /review did not launch the bounded review workflow");
685
695
  }
686
- const scsOnResult = await runChat("/scs\n");
696
+ const scsDefaultStatusResult = await runChat("/scs status\n");
697
+ if (!scsDefaultStatusResult.stdout.includes("SCS mode: auto")) {
698
+ throw new Error("interactive /scs status did not show default auto mode");
699
+ }
700
+ const statusFooterResult = await runChat("/status\n");
701
+ if (
702
+ !statusFooterResult.stdout.includes(`cwd=${tempRoot} scs=auto aaps=off venice=off`) ||
703
+ !statusFooterResult.stdout.includes("permission=")
704
+ ) {
705
+ throw new Error("interactive /status did not include scs/aaps/venice mode state on the cwd line");
706
+ }
707
+ const scsOnResult = await runChat("/scs on\n");
687
708
  if (!scsOnResult.stdout.includes("scs=on")) {
688
- throw new Error("interactive /scs did not toggle SCS on");
709
+ throw new Error("interactive /scs on did not enable SCS");
689
710
  }
690
711
  const legacyScsAlias = "/enable" + "ss";
691
712
  const oldScsAliasResult = await runChat(`${legacyScsAlias}\n/exit\n`);
@@ -696,14 +717,18 @@ try {
696
717
  if (!scsOffResult.stdout.includes("scs=off")) {
697
718
  throw new Error("interactive /scs did not toggle SCS off");
698
719
  }
699
- const scsStatusResult = await runChat("/scs status\n");
720
+ const scsStatusResult = await runCli(["chat", "--provider", "mock", "--routing", "manual", "--profile", "code", "--no-scs"], "/scs status\n");
700
721
  if (!scsStatusResult.stdout.includes("SCS mode: off")) {
701
- throw new Error("interactive /scs status did not show current mode");
722
+ throw new Error("interactive /scs status did not show explicit off mode");
702
723
  }
703
724
  const scsAutoResult = await runChat("/scs auto\n");
704
725
  if (!scsAutoResult.stdout.includes("scs=auto")) {
705
726
  throw new Error("interactive /scs auto did not enable auto mode");
706
727
  }
728
+ const aapsAutoResult = await runChat("/aaps auto\n");
729
+ if (!aapsAutoResult.stdout.includes("aaps=auto profile=aaps")) {
730
+ throw new Error("interactive /aaps auto did not enable AAPS auto mode");
731
+ }
707
732
  const safeResult = await runChat("/safe\n");
708
733
  if (!safeResult.stdout.includes("permission=safe") || !safeResult.stdout.includes("writePolicy=prompt")) {
709
734
  throw new Error("interactive /safe did not switch to safe permission mode");
@@ -441,6 +441,18 @@ try {
441
441
  );
442
442
  assert(androidReadonlyProbePolicy.allowed, "Android host read-only probes should not require full-host destructive access");
443
443
  assert(androidReadonlyProbePolicy.category === "read-only", "Android host probes should remain read-only");
444
+ const hostLocalhostJsonProbePolicy = evaluateCommandPolicy(
445
+ "curl -s http://127.0.0.1:9222/json/version | python3 -m json.tool",
446
+ hostWorkspacePolicy
447
+ );
448
+ assert(hostLocalhostJsonProbePolicy.allowed, "host localhost JSON probe should not require full-host destructive access");
449
+ assert(hostLocalhostJsonProbePolicy.category === "network-fetch", "host localhost JSON probe should stay classified as network-fetch");
450
+ const absolutePythonHelperPolicy = evaluateCommandPolicy(
451
+ "/home/lachlan/miniconda3/bin/python scripts/xyq_cdp_browser.py list-pages",
452
+ hostWorkspacePolicy
453
+ );
454
+ assert(absolutePythonHelperPolicy.allowed, "host absolute Python helper script should be allowed without full-host destructive access");
455
+ assert(absolutePythonHelperPolicy.category === "toolchain", "host absolute Python helper should remain classified as toolchain");
444
456
  const androidGradleBuildPolicy = evaluateCommandPolicy("cd android-app && ./gradlew :app:assembleDebug", hostWorkspacePolicy);
445
457
  assert(androidGradleBuildPolicy.allowed, "workspace-local Gradle Android build should be allowed in host workspace mode");
446
458
  assert(androidGradleBuildPolicy.category === "toolchain", "workspace-local Gradle Android build should be toolchain");
@@ -555,6 +567,18 @@ try {
555
567
  failedNetworkAdvice.instruction.includes("Stop and present this blocker"),
556
568
  "network failure advice did not tell the model to stop and ask"
557
569
  );
570
+ const failedDockerLocalhostAdvice = buildFailedCommandAdvice({
571
+ args: { command: "curl -fsS http://127.0.0.1:9222/json/version" },
572
+ commandPolicy: evaluateCommandPolicy("curl -fsS http://127.0.0.1:9222/json/version", dockerWorkspacePolicy),
573
+ commandResult: { ok: false, stderr: "curl: (7) Failed to connect to 127.0.0.1 port 9222: Connection refused" },
574
+ config: dockerWorkspacePolicy,
575
+ state: { sessionId: "coding-localhost-cdp-smoke" },
576
+ });
577
+ assert(failedDockerLocalhostAdvice?.failureKind === "host-local-service", "Docker localhost failure advice was not generated");
578
+ assert(
579
+ failedDockerLocalhostAdvice.suggestedCommand.includes("--sandbox-mode host"),
580
+ "Docker localhost advice did not suggest host mode"
581
+ );
558
582
  const failedOutsidePathAdvice = buildFailedCommandAdvice({
559
583
  args: { command: 'echo "outside permission test" > /home/lachlan/ProjectsLFS/outside.txt' },
560
584
  commandPolicy: evaluateCommandPolicy('echo "outside permission test" > /home/lachlan/ProjectsLFS/outside.txt', dockerWorkspacePolicy),
@@ -1149,6 +1173,8 @@ try {
1149
1173
  "command_policy_safe_chmod_sequence",
1150
1174
  "command_policy_host_workspace_chmod",
1151
1175
  "command_policy_android_host_probes",
1176
+ "command_policy_host_localhost_json_probe",
1177
+ "command_policy_absolute_python_helper",
1152
1178
  "command_policy_android_gradle_build",
1153
1179
  "command_policy_android_gradle_build_with_safe_env",
1154
1180
  "command_policy_cd_workspace",
@@ -5,13 +5,19 @@ import path from "node:path";
5
5
  import { fileURLToPath } from "node:url";
6
6
  import { runAgent } from "../src/agent-runner.js";
7
7
  import { resolveRuntimeConfig } from "../src/config.js";
8
- import { shouldActivateScs } from "../src/scs-controller.js";
8
+ import {
9
+ browserSubmitFinishIssue,
10
+ isSuspiciousBroadBrowserToolResult,
11
+ shouldActivateScs,
12
+ shouldReviewToolResult,
13
+ } from "../src/scs-controller.js";
9
14
  import {
10
15
  createStepBudgetState,
11
16
  decideStepBudgetExtension,
12
17
  normalizeDynamicStepsMode,
13
18
  } from "../src/step-budget-controller.js";
14
19
  import { SessionStore } from "../src/session-store.js";
20
+ import { recommendedMaxStepsForTask } from "../src/engineering-guidance.js";
15
21
 
16
22
  const repoRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
17
23
  const tempRoot = await fs.mkdtemp(path.join(os.tmpdir(), "agintiflow-dynamic-budget-"));
@@ -44,10 +50,67 @@ try {
44
50
  }),
45
51
  "/scs auto should activate for complex engineering prompts"
46
52
  );
53
+ assert(
54
+ shouldActivateScs("auto", {
55
+ goal: "Use Chrome Driver/CDP on 127.0.0.1:9222 to upload five reference images, choose an asset-library video, submit the browser form, and monitor progress.",
56
+ taskProfile: "auto",
57
+ complexityScore: 1,
58
+ }),
59
+ "/scs auto should activate for browser automation and host-local CDP workflows"
60
+ );
47
61
  assert(
48
62
  !shouldActivateScs("auto", { goal: "say hello", taskProfile: "auto", complexityScore: 0 }),
49
63
  "/scs auto should stay off for trivial prompts"
50
64
  );
65
+ const broadBrowserClick = {
66
+ toolName: "run_command",
67
+ ok: true,
68
+ args: {
69
+ command: "python scripts/browser_cdp.py click-text PAGE \"Create\"",
70
+ },
71
+ stdout: JSON.stringify({
72
+ ok: true,
73
+ text: Array(30)
74
+ .fill("New chat\nAsset library\nHistory\nAll\nYesterday\nThis month\nSettings\nUpload reference\nSubmit prompt")
75
+ .join("\n"),
76
+ x: 650,
77
+ y: 390,
78
+ }),
79
+ };
80
+ assert(
81
+ isSuspiciousBroadBrowserToolResult(broadBrowserClick),
82
+ "SCS should flag successful browser clicks that return broad whole-page text"
83
+ );
84
+ assert(
85
+ shouldReviewToolResult(broadBrowserClick, { meta: {} }),
86
+ "SCS should review suspicious broad browser click results"
87
+ );
88
+ assert(
89
+ !isSuspiciousBroadBrowserToolResult({
90
+ toolName: "run_command",
91
+ ok: true,
92
+ args: { command: "echo ok" },
93
+ stdout: "ok",
94
+ }),
95
+ "SCS should not flag ordinary successful shell output as a browser click problem"
96
+ );
97
+ assert(
98
+ recommendedMaxStepsForTask({
99
+ goal: "Use Chrome CDP to upload five images, select an asset-library video, choose non-VIP model, and submit the Xiaoyunque browser composer.",
100
+ }) >= 48,
101
+ "browser submit workflows need a larger default step budget"
102
+ );
103
+ assert(
104
+ browserSubmitFinishIssue(
105
+ "小云雀网页上传五张图,从资产库选择参考视频,然后提交生成",
106
+ "资产库旧三人视频 未执行;提交 未执行;步骤不足。"
107
+ ),
108
+ "SCS finish gate should reject unfinished browser submit reports"
109
+ );
110
+ assert(
111
+ !browserSubmitFinishIssue("小云雀网页提交生成", "停止:积分不足,需要用户处理 credits not enough。"),
112
+ "SCS finish gate should allow real external browser blockers"
113
+ );
51
114
 
52
115
  const normalBudget = createStepBudgetState(
53
116
  {
@@ -131,6 +194,7 @@ try {
131
194
  sessionId: "dynamic-step-budget-smoke",
132
195
  }
133
196
  );
197
+ assert(config.enableScs === "auto", "runtime config should default SCS mode to auto");
134
198
  const run = await runAgent(config);
135
199
  assert(!run.stopped, "mock run stopped instead of using dynamic extension");
136
200
  const written = await fs.readFile(path.join(workspace, "notes/dynamic-budget.md"), "utf8");
@@ -11,7 +11,7 @@ import {
11
11
  } from "../src/model-routing.js";
12
12
  import { normalizeTextToolCallResponse, parseTextToolCalls, usesTextToolProtocol } from "../src/model-client.js";
13
13
  import { modelRoleChoices, selectorVisibleWindow } from "../src/interactive-cli.js";
14
- import { buildScsEvidencePack, buildSupervisorInstruction } from "../src/scs-controller.js";
14
+ import { buildScsEvidencePack, buildSupervisorInstruction, shouldRequestScsReplan } from "../src/scs-controller.js";
15
15
 
16
16
  const repoRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
17
17
 
@@ -219,6 +219,10 @@ assert(!usesTextToolProtocol({ provider: "venice", model: "venice-uncensored-1-2
219
219
  const scsInstruction = buildSupervisorInstruction({ plan: "Create one file.", acceptanceCriteria: ["File exists."] });
220
220
  assert(scsInstruction.includes("Student-Committee-Supervisor"), "SCS supervisor instruction should define the acronym");
221
221
  assert(!scsInstruction.includes("Syntax-Checker Sentinel"), "SCS supervisor instruction should not allow alternate acronym expansions");
222
+ assert(scsInstruction.includes("student is the independent validator"), "SCS supervisor instruction should define student as validator");
223
+ assert(shouldRequestScsReplan({ decision: "finish_rejected" }), "finish rejection should trigger committee replan");
224
+ assert(shouldRequestScsReplan({ decision: "rethink_plan" }), "student rethink should trigger committee replan");
225
+ assert(!shouldRequestScsReplan({ decision: "finish_allowed" }), "finish approval should not trigger committee replan");
222
226
  const longStdout = [
223
227
  "=== Student-Committee-Supervisor present ===",
224
228
  "3:SCS stands for **Student-Committee-Supervisor**",
@@ -270,6 +274,7 @@ console.log(
270
274
  "requested-tools-parser",
271
275
  "malformed-text-tool-retry",
272
276
  "scs-supervisor-identity",
277
+ "scs-student-validator-replan",
273
278
  "scs-evidence-stdout",
274
279
  "cli-models-command",
275
280
  "venice-shortcut",
@@ -22,6 +22,7 @@ assert(skills.length >= 27, "expected built-in skills to load");
22
22
  for (const required of [
23
23
  "aaps",
24
24
  "autonomous-artifact-pipeline",
25
+ "browser-automation",
25
26
  "code",
26
27
  "code-review",
27
28
  "data-analysis",
@@ -56,6 +57,13 @@ for (const required of [
56
57
  }
57
58
 
58
59
  assert(selectedIds("write a beautiful React website and preview it").includes("website-app"), "website prompt did not select website-app");
60
+ assert(
61
+ selectedIds("control an existing Chrome CDP browser composer, upload images, choose model duration, and submit").includes(
62
+ "browser-automation"
63
+ ),
64
+ "browser automation prompt did not select browser-automation"
65
+ );
66
+ assert(selectedIds("小云雀 网页 上传 五张图 从资产库选择视频 提交").includes("browser-automation"), "Chinese XYQ prompt did not select browser-automation");
59
67
  assert(selectedIds("write a LaTeX paper and compile a PDF").includes("latex-manuscript"), "latex prompt did not select latex-manuscript");
60
68
  assert(selectedIds("edit a Microsoft Word docx and preserve the original").includes("word-documents"), "docx prompt did not select word-documents");
61
69
  assert(selectedIds("generate a logo image with grsai nanobanana").includes("image-generation"), "image prompt did not select image-generation");
@@ -0,0 +1,56 @@
1
+ ---
2
+ id: browser-automation
3
+ label: Browser Automation
4
+ description: Control existing browser sessions, Chrome/CDP pages, web composers, upload dialogs, asset pickers, model selectors, forms, and submit/publish workflows with inspect-set-verify discipline.
5
+ triggers:
6
+ - browser
7
+ - chrome
8
+ - cdp
9
+ - chromedriver
10
+ - playwright
11
+ - selenium
12
+ - web ui
13
+ - website
14
+ - upload
15
+ - attach
16
+ - asset library
17
+ - submit
18
+ - publish
19
+ - model selector
20
+ - prompt composer
21
+ - 小云雀
22
+ - 浏览器
23
+ - 网页
24
+ - 上传
25
+ - 资产库
26
+ - 提交
27
+ tools:
28
+ - open_url
29
+ - click
30
+ - type
31
+ - press
32
+ - wait
33
+ - run_command
34
+ - read_image
35
+ - read_file
36
+ - search_files
37
+ ---
38
+ # Browser Automation
39
+
40
+ Treat browser work as state reconciliation, not passive inspection.
41
+
42
+ Workflow:
43
+
44
+ 1. Identify the active page and the target final state: page/workspace, mode, model, duration, attachments, prompt text, and submit state.
45
+ 2. Inspect the current state from the latest snapshot, project helper scripts, screenshots, or read-only CDP/Playwright queries.
46
+ 3. If a required control is absent or unknown, set it with the smallest scoped action, then wait and verify. Do not stop just because the first state dump lacks a field.
47
+ 4. Prefer scoped selectors inside the relevant composer, toolbar, modal, asset picker, or form. Broad text clicks over the whole page are unreliable.
48
+ 5. If a helper reports `ok: true` but returns whole-page text, history/sidebar/nav text, unrelated examples, or an unscoped match, treat it as a wrong target and retry with scoped JS, coordinates from a screenshot, or a narrower selector.
49
+ 6. For uploads or asset-library selection, verify visible chips, thumbnails, filenames, counters, or previews before submitting.
50
+ 7. When multiple browser tabs or CDP targets exist, reconcile the target with the user-visible tab. Bring the controlled page to the front when possible, name the exact page id, URL, and workflow, and save screenshot evidence. Do not report that the user can see an upload if only a background page was verified.
51
+ 8. For model/duration/mode controls, distinguish selected state from ads, recommendations, and history labels.
52
+ 9. For model selectors, honor the exact requested tier. If the user asked for a non-VIP model and the toolbar says VIP, open the selector and choose a non-VIP option; if none exists, stop with that evidence instead of assuming account membership changes the selected model.
53
+ 10. Before irreversible or externally visible actions such as submit, publish, purchase, or account changes, verify all requested state. If verification remains impossible after a bounded set attempt, stop with the exact blocker and evidence.
54
+ 11. If the user requested submit/publish/generation, do not finish merely because time or steps are running low while assets, reference media, model choice, or the final submit remain skipped. Continue with a narrower action or stop only for an external blocker such as login, credits, captcha, server/internal error, missing account permission, or a user confirmation dialog.
55
+
56
+ For logged-in browser sessions, preserve the user’s state. Do not open new tabs, navigate to home/history, or close pages unless the current composer is unusable and the user allowed it.