# SGrobot Adapter Implementation Plan > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. **Goal:** Build a reusable generator that turns one rrweb semantic trace into SGrobot-compatible `PlanTemplate.toml` and runtime `SKILL.toml` artifacts without changing SGrobot core. **Architecture:** Keep this repository as a Codex skill plus deterministic generator. The generator writes one business-specific plan and one business-specific sgBrowser runtime skill per recording, with the semantic trace baked into the generated page script and saved beside it as evidence. **Tech Stack:** Node.js ESM, `node:test`, SGrobot `PlanTemplate.toml`, SGrobot runtime `SKILL.toml`, sgBrowser `sgBrowserExcuteJsCodeByDomain`. --- ### Task 1: Generator Contract **Files:** - Create: `tests/generate_sgrobot_flow.test.mjs` - Create: `scripts/generate_sgrobot_flow.mjs` - Create: `package.json` - [ ] **Step 1: Write the failing tests** ```js import { test } from "node:test"; import assert from "node:assert/strict"; import { mkdtemp, readFile, rm } from "node:fs/promises"; import { tmpdir } from "node:os"; import path from "node:path"; import { generateSgRobotArtifacts, writeArtifacts } from "../scripts/generate_sgrobot_flow.mjs"; const trace = { id: "expense-approval", name: "费用审批", description: "打开审批页,填写意见并点击同意。", startUrl: "https://oa.example.test/expense/123", steps: [ { type: "assertText", text: "费用审批", label: "确认在审批页" }, { type: "fill", selector: "textarea[name='comment']", value: "同意", label: "填写审批意见" }, { type: "click", selector: "button[data-action='approve']", label: "点击同意", risk: "write" } ] }; test("generates SGrobot plan and runtime skill artifacts", () => { const result = generateSgRobotArtifacts(trace, { defaultMode: "execute" }); assert.equal(result.summary.planId, "rrweb-expense-approval"); assert.equal(result.summary.skillName, "rrweb-expense-approval-execute"); assert.equal(result.summary.requiresApproval, true); assert.equal(result.files.get("plan_templates/rrweb-expense-approval/PlanTemplate.toml").includes('skills = ["rrweb-expense-approval-execute"]'), true); assert.equal(result.files.get(".sgclaw-workspace/skills/rrweb-expense-approval-execute/SKILL.toml").includes('command = "sgBrowserExcuteJsCodeByDomain"'), true); assert.equal(result.files.get(".sgclaw-workspace/skills/rrweb-expense-approval-execute/SKILL.toml").includes('expected_domain = "oa.example.test"'), true); assert.equal(result.files.get(".sgclaw-workspace/skills/rrweb-expense-approval-execute/scripts/execute_trace.js").includes('"default_mode": "execute"'), true); }); test("writes generated artifacts under a SGrobot repository root", async () => { const root = await mkdtemp(path.join(tmpdir(), "rrweb-sgrobot-")); try { const result = generateSgRobotArtifacts(trace); await writeArtifacts(root, result.files); const plan = await readFile(path.join(root, "plan_templates/rrweb-expense-approval/PlanTemplate.toml"), "utf8"); const skill = await readFile(path.join(root, ".sgclaw-workspace/skills/rrweb-expense-approval-execute/SKILL.toml"), "utf8"); const evidence = await readFile(path.join(root, ".sgclaw-workspace/skills/rrweb-expense-approval-execute/trace.semantic.json"), "utf8"); assert.match(plan, /skills = \["browser\.open_url"\]/); assert.match(skill, /script_path = "scripts\/execute_trace.js"/); assert.equal(JSON.parse(evidence).id, "expense-approval"); } finally { await rm(root, { recursive: true, force: true }); } }); ``` - [ ] **Step 2: Run test to verify it fails** Run: `node --test tests/generate_sgrobot_flow.test.mjs` Expected: FAIL with `Cannot find module '../scripts/generate_sgrobot_flow.mjs'`. - [ ] **Step 3: Implement the generator** Create `scripts/generate_sgrobot_flow.mjs` exporting `generateSgRobotArtifacts(trace, options)` and `writeArtifacts(root, files)`. The generator must validate `id`, `name`, `startUrl`, and `steps`, derive `expected_domain` from `startUrl`, emit SGrobot paths, and support `defaultMode` of `dry-run` or `execute`. - [ ] **Step 4: Add package metadata** Create `package.json` with: ```json { "name": "rrweb-sgrobot-skill", "version": "0.1.0", "type": "module", "private": true, "scripts": { "test": "node --test tests/*.test.mjs", "generate:sgrobot": "node scripts/generate_sgrobot_flow.mjs" } } ``` - [ ] **Step 5: Run test to verify it passes** Run: `npm test` Expected: PASS with both generator tests green. ### Task 2: Codex Skill Wrapper **Files:** - Create: `SKILL.md` - Create: `references/sgrobot-adapter.md` - Create: `examples/basic-trace.json` - [ ] **Step 1: Write the skill instructions** Create a concise `SKILL.md` that tells Codex to use `scripts/generate_sgrobot_flow.mjs` when adapting rrweb semantic traces for SGrobot. It must state that `.agents/skills/**/SKILL.md` is only an agent helper, while SGrobot runtime artifacts are `PlanTemplate.toml` and `.sgclaw-workspace/skills/**/SKILL.toml`. - [ ] **Step 2: Add focused SGrobot mapping reference** Create `references/sgrobot-adapter.md` with the SGrobot-specific mapping rules: one generated plan per recording, one generated runtime skill per recording, `browser.open_url` first, generated sgBrowser execution skill second, optional `json.save_result` third, and step-level approval when execute mode includes mutating actions. - [ ] **Step 3: Add a realistic example trace** Create `examples/basic-trace.json` using the same schema covered by the test: `id`, `name`, `description`, `startUrl`, and `steps`. - [ ] **Step 4: Validate the skill folder** Run: `python3 /Users/zhaoyilun/.codex/skills/.system/skill-creator/scripts/quick_validate.py /Users/zhaoyilun/Documents/rrweb-skill` Expected: PASS. ### Task 3: Verification Against SGrobot Shape **Files:** - Read-only check: `/Users/zhaoyilun/projects/sgrobot-architecture-design/docs/concepts/skill-and-plan-template.md` - Read-only check: `/Users/zhaoyilun/projects/sgrobot-architecture-design/docs/how-to/add-skill.md` - [ ] **Step 1: Generate sample output to a temp directory** Run: `node scripts/generate_sgrobot_flow.mjs --trace examples/basic-trace.json --out /tmp/rrweb-sgrobot-sample --default-mode dry-run --force` Expected: the command prints paths for the plan, skill, runtime script, and trace evidence. - [ ] **Step 2: Inspect generated files** Run: `find /tmp/rrweb-sgrobot-sample -type f | sort` Expected: files exist under `plan_templates/rrweb-expense-approval/` and `.sgclaw-workspace/skills/rrweb-expense-approval-execute/`. - [ ] **Step 3: Re-run tests** Run: `npm test` Expected: PASS.