@aiguru/google-web-operations 0.6.4
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/.env.example +42 -0
- package/README.md +110 -0
- package/apps/cli/src/index.js +286 -0
- package/apps/mcp-server/src/index.js +360 -0
- package/apps/worker/src/index.js +96 -0
- package/apps/worker/src/loop.js +46 -0
- package/bin/gwo.js +67 -0
- package/docs/BOOTSTRAP-NEXT-PROMPT.md +57 -0
- package/docs/GETTING-STARTED.he.md +63 -0
- package/docs/HOSTED-WORKER.md +36 -0
- package/docs/INSTALL.he.md +57 -0
- package/docs/PRODUCT-TECHNICAL-SPEC-v0.2.md +153 -0
- package/docs/PRODUCT-TECHNICAL-SPEC-v0.3.md +86 -0
- package/docs/PRODUCT-TECHNICAL-SPEC-v0.4.md +92 -0
- package/docs/PRODUCT-TECHNICAL-SPEC-v0.5.md +94 -0
- package/docs/PRODUCT-TECHNICAL-SPEC-v0.6.md +98 -0
- package/docs/SECURITY.md +69 -0
- package/docs/SITE-ADAPTERS.md +87 -0
- package/docs/adr/ADR-001-shared-mcp-core.md +27 -0
- package/docs/adr/ADR-002-policy-gated-writes.md +18 -0
- package/docs/adr/ADR-003-single-source-playbooks.md +18 -0
- package/docs/adr/ADR-004-native-typescript-runtime.md +16 -0
- package/docs/adr/ADR-005-two-token-publish.md +22 -0
- package/docs/adr/ADR-006-one-package-one-installer.md +20 -0
- package/hosts/claude/.claude-plugin/plugin.json +9 -0
- package/hosts/claude/.mcp.json +10 -0
- package/hosts/claude/README.md +7 -0
- package/hosts/claude/commands/gwo-add-site.md +7 -0
- package/hosts/claude/commands/gwo-daily.md +7 -0
- package/hosts/claude/commands/gwo-measure.md +7 -0
- package/hosts/claude/commands/gwo-monthly.md +7 -0
- package/hosts/claude/commands/gwo-onboard.md +7 -0
- package/hosts/claude/commands/gwo-scan.md +7 -0
- package/hosts/claude/commands/gwo-setup.md +7 -0
- package/hosts/claude/commands/gwo-triage.md +7 -0
- package/hosts/claude/commands/gwo-weekly.md +7 -0
- package/hosts/claude/skills/gwo-client-report-template/SKILL.md +36 -0
- package/hosts/claude/skills/gwo-content-brief/SKILL.md +60 -0
- package/hosts/claude/skills/gwo-daily/SKILL.md +47 -0
- package/hosts/claude/skills/gwo-measurement/SKILL.md +92 -0
- package/hosts/claude/skills/gwo-monthly/SKILL.md +30 -0
- package/hosts/claude/skills/gwo-onboarding/SKILL.md +27 -0
- package/hosts/claude/skills/gwo-operating-model/SKILL.md +76 -0
- package/hosts/claude/skills/gwo-setup/SKILL.md +42 -0
- package/hosts/claude/skills/gwo-triage/SKILL.md +37 -0
- package/hosts/claude/skills/gwo-weekly/SKILL.md +48 -0
- package/hosts/codex/.codex/config.template.toml +5 -0
- package/hosts/codex/.codex-plugin/plugin.json +30 -0
- package/hosts/codex/AGENTS.md +470 -0
- package/hosts/codex/README.md +13 -0
- package/hosts/codex/skills/gwo-client-report-template/SKILL.md +36 -0
- package/hosts/codex/skills/gwo-content-brief/SKILL.md +60 -0
- package/hosts/codex/skills/gwo-daily/SKILL.md +47 -0
- package/hosts/codex/skills/gwo-measurement/SKILL.md +92 -0
- package/hosts/codex/skills/gwo-monthly/SKILL.md +30 -0
- package/hosts/codex/skills/gwo-onboarding/SKILL.md +27 -0
- package/hosts/codex/skills/gwo-operating-model/SKILL.md +76 -0
- package/hosts/codex/skills/gwo-setup/SKILL.md +42 -0
- package/hosts/codex/skills/gwo-triage/SKILL.md +37 -0
- package/hosts/codex/skills/gwo-weekly/SKILL.md +48 -0
- package/package.json +24 -0
- package/packages/connectors/browser/src/index.js +122 -0
- package/packages/connectors/docx/src/index.js +122 -0
- package/packages/connectors/github/src/index.js +102 -0
- package/packages/connectors/google/src/auth.js +73 -0
- package/packages/connectors/google/src/discover.js +135 -0
- package/packages/connectors/google/src/ga4.js +42 -0
- package/packages/connectors/google/src/gsc.js +49 -0
- package/packages/connectors/google/src/gtm.js +261 -0
- package/packages/connectors/google/src/index.js +8 -0
- package/packages/connectors/google/src/oauth.js +198 -0
- package/packages/connectors/google/src/pagespeed.js +48 -0
- package/packages/connectors/google/src/token-store.js +89 -0
- package/packages/connectors/odoo/src/index.js +206 -0
- package/packages/connectors/repo/src/index.js +94 -0
- package/packages/connectors/resend/src/index.js +30 -0
- package/packages/connectors/web-crawler/src/a11y.js +91 -0
- package/packages/connectors/web-crawler/src/fetch.js +165 -0
- package/packages/connectors/web-crawler/src/index.js +69 -0
- package/packages/connectors/web-crawler/src/parse.js +157 -0
- package/packages/core/src/adapters.js +27 -0
- package/packages/core/src/admin.js +232 -0
- package/packages/core/src/content.js +213 -0
- package/packages/core/src/doctor.js +39 -0
- package/packages/core/src/escalate.js +36 -0
- package/packages/core/src/gtm-ops.js +311 -0
- package/packages/core/src/index.js +13 -0
- package/packages/core/src/operations.js +239 -0
- package/packages/core/src/paths.js +46 -0
- package/packages/core/src/registry.js +114 -0
- package/packages/core/src/report/monthly.js +272 -0
- package/packages/core/src/scan/render.js +40 -0
- package/packages/core/src/scan/rules.js +289 -0
- package/packages/core/src/scan/suppress.js +37 -0
- package/packages/core/src/types.js +10 -0
- package/packages/core/src/writes.js +50 -0
- package/packages/playbooks/00-operating-model.md +74 -0
- package/packages/playbooks/10-daily.md +45 -0
- package/packages/playbooks/20-weekly.md +46 -0
- package/packages/playbooks/30-monthly.md +28 -0
- package/packages/playbooks/40-triage.md +35 -0
- package/packages/playbooks/50-onboarding.md +25 -0
- package/packages/playbooks/60-content-brief.md +58 -0
- package/packages/playbooks/70-measurement.md +90 -0
- package/packages/playbooks/80-setup.md +40 -0
- package/packages/playbooks/90-client-report-template.md +34 -0
- package/packages/policy/src/index.js +115 -0
- package/packages/storage/src/index.js +131 -0
- package/policies/default.yaml +90 -0
- package/sites/schema.yaml +71 -0
- package/sites/secrets.example.yaml +6 -0
- package/tools/build-hosts.js +118 -0
- package/tools/build-package.js +43 -0
- package/tools/install.js +145 -0
- package/tools/schedule.ps1 +37 -0
- package/tools/smoke-mcp.js +61 -0
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# Google Web Operations: התחלה מהירה
|
|
2
|
+
|
|
3
|
+
מערכת תפעול שוטף לאתרי לקוחות בגוגל ובמנועי תשובה מבוססי AI. היא סורקת, קוראת Search Console, Analytics ו‑Tag Manager, מתקנת מה שמותר לה לתקן, מאמתת כל שינוי, ורושמת הכול. עובדים איתה מתוך Claude Code או Codex, בשיחה.
|
|
4
|
+
|
|
5
|
+
## התקנה (פעם אחת בכל מחשב)
|
|
6
|
+
|
|
7
|
+
דרישות: Node 22.18 ומעלה.
|
|
8
|
+
|
|
9
|
+
1. בטרמינל:
|
|
10
|
+
```
|
|
11
|
+
npm i -g @aiguru/google-web-operations
|
|
12
|
+
gwo install
|
|
13
|
+
```
|
|
14
|
+
2. הפעלה מחדש של Claude Code או Codex.
|
|
15
|
+
|
|
16
|
+
`gwo install` רושם את שרת ה‑MCP, את הסקילים ואת הפקודות בשני ההוסטים, ויוצר את תיקיית המצב `~/.gwo` (אתרים, נתונים, סודות, הגדרות). שדרוג בעתיד: `gwo update`.
|
|
17
|
+
|
|
18
|
+
לבדיקה שהכול במקום: `gwo doctor`.
|
|
19
|
+
|
|
20
|
+
## השיחה הראשונה
|
|
21
|
+
|
|
22
|
+
ב‑Claude Code: `/gwo-setup`. ב‑Codex: "הגדר את Google Web Operations". הסוכן קורא את מצב ההגדרה ומוביל צעד אחר צעד:
|
|
23
|
+
|
|
24
|
+
1. **חיבור לגוגל.** פרויקט Google Cloud אחד לכל הלקוחות, לקוח OAuth מסוג Desktop app, הורדת ה‑JSON. הסוכן מבקש את הנתיב לקובץ, לא את התוכן. ואז דפדפן נפתח להסכמה עם חשבון התפעול של החברה.
|
|
25
|
+
2. **אתר ראשון.** כתובת, שם, פלטפורמה (Odoo, Next.js, WordPress, אחר). השאר ברירות מחדל. הסוכן מבצע סריקת בסיס ומנסח ללקוח את רשימת ההרשאות שהוא צריך לתת לחשבון התפעול: Search Console, GA4, ובמידת הצורך Tag Manager.
|
|
26
|
+
3. **אחרי שהלקוח נתן הרשאות.** "גלה את הנכסים" ממלא את המזהים בקובץ האתר.
|
|
27
|
+
|
|
28
|
+
## עבודה שוטפת
|
|
29
|
+
|
|
30
|
+
| פקודה | מה קורה |
|
|
31
|
+
|---|---|
|
|
32
|
+
| `/gwo-daily` | בדיקת בריאות שקטה. מדווח רק על שינויים ותקלות |
|
|
33
|
+
| `/gwo-weekly` | סבב שיפורים: ממצאים פתוחים, הזדמנויות מ‑Search Console, תיקונים במסגרת המדיניות |
|
|
34
|
+
| `/gwo-monthly` | סריקה עמוקה ודוח לקוח כקובץ Word |
|
|
35
|
+
| `/gwo-triage <site>` | חקירת תקלה: ירידה בתנועה, אובדן אינדוקס, מדידה שנשברה |
|
|
36
|
+
| `/gwo-measure <site>` | אודיט מדידה ושינויים ב‑Tag Manager דרך סביבת עבודה מבוקרת |
|
|
37
|
+
| `/gwo-scan <site>` | סריקה אחת עכשיו |
|
|
38
|
+
| `/gwo-add-site <url>` | רישום אתר חדש |
|
|
39
|
+
|
|
40
|
+
ב‑Codex אין פקודות slash, אבל אותם סקילים נטענים לפי הכוונה: "תריץ את הבדיקה היומית", "מה קרה לתנועה של דורית", "דוח חודשי לאתר X".
|
|
41
|
+
|
|
42
|
+
## שלוש רמות סיכון, ולא יותר
|
|
43
|
+
|
|
44
|
+
- **auto**: הסוכן מבצע ומדווח. סריקות, קריאות, הגשת sitemap, מילוי תיאור ריק.
|
|
45
|
+
- **approval_required**: הסוכן מציע ומציג טוקן בצורה `<site>:<action>`. מדביקים את הטוקן בחזרה, והוא מבצע. כותרות, נתונים מובנים, אירועי מפתח, שינויי Tag Manager.
|
|
46
|
+
- **protected**: לעולם לא. מחיקות, חיוב, הרשאות משתמשים.
|
|
47
|
+
|
|
48
|
+
פרסום ב‑Tag Manager דורש גם review token שמחושב מהדיף שהוצג. אם משהו זז מאז, הפרסום נדחה.
|
|
49
|
+
|
|
50
|
+
## החלטות אתר
|
|
51
|
+
|
|
52
|
+
כשלקוח אומר "זה בכוונה" (למשל GA4 בלי Tag Manager), אומרים לסוכן והוא רושם דיכוי עם הסיבה. הממצא נספר בכותרת של כל דוח אבל מפסיק להיות רעש.
|
|
53
|
+
|
|
54
|
+
## איפה הדברים
|
|
55
|
+
|
|
56
|
+
- `~/.gwo/sites/` קובץ YAML לכל אתר. סודות ב‑`<host>.secrets.yaml`, ידנית בלבד.
|
|
57
|
+
- `~/.gwo/.gwo-data/<site>/` סריקות, snapshots, יומן ביקורת, דוחות.
|
|
58
|
+
- `~/.gwo/.env` הגדרות: תבנית Word לדוחות, Resend למשלוח, GitHub ל‑pull requests.
|
|
59
|
+
- `~/.gwo/secrets/` לקוח OAuth וטוקן מוצפן.
|
|
60
|
+
|
|
61
|
+
## עזרה
|
|
62
|
+
|
|
63
|
+
`gwo` בלי פרמטרים מציג את כל הפקודות. `gwo doctor` אומר מה חסר ומה הצעד הבא.
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# Hosted worker
|
|
2
|
+
|
|
3
|
+
The daily and weekly runs should not depend on one laptop being on at 07:00. Any always-on Linux host works: a small VM, a NAS, a container platform. The worker needs no agent, no browser and no inbound ports.
|
|
4
|
+
|
|
5
|
+
## What runs
|
|
6
|
+
|
|
7
|
+
`gwo worker loop` (the container's default command) runs `gwo worker daily` every day at `GWO_DAILY_AT` and `gwo worker weekly` on `GWO_WEEKLY_DAY` at `GWO_WEEKLY_AT`, in `TZ`. With `RESEND_API_KEY` set, reports are emailed; otherwise they stay under `.gwo-data/_runs/` in the state volume. Each run is a child process with its exit code logged (0 healthy, 2 escalations, 1 failures).
|
|
8
|
+
|
|
9
|
+
## Build and run
|
|
10
|
+
|
|
11
|
+
```
|
|
12
|
+
docker compose -f deploy/compose.yml up -d
|
|
13
|
+
docker logs -f gwo-worker
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
The image compiles the package (`npm run build:package`) and installs runtime dependencies only. State lives in the `gwo-home` volume at `/home/gwo/.gwo`, the same layout as `~/.gwo` on a workstation: `sites/`, `.gwo-data/`, `secrets/`, `.env`.
|
|
17
|
+
|
|
18
|
+
## Hand over configuration
|
|
19
|
+
|
|
20
|
+
1. **Sites.** Copy `sites/*.yaml` (and any `*.secrets.yaml`) into the volume: `docker cp sites/. gwo-worker:/home/gwo/.gwo/sites/`.
|
|
21
|
+
2. **Environment.** Put `RESEND_API_KEY`, `GWO_REPORT_FROM`, `GWO_REPORT_TO` in `/home/gwo/.gwo/.env` inside the volume (or as container environment).
|
|
22
|
+
3. **Google token.** A headless host cannot complete the browser consent, so authorise on a workstation with the portable store and copy the result:
|
|
23
|
+
|
|
24
|
+
```
|
|
25
|
+
GWO_TOKEN_STORE=aes gwo auth login # on the workstation; writes secrets/google-token.enc and secrets/.token-key
|
|
26
|
+
docker cp secrets/google-token.enc gwo-worker:/home/gwo/.gwo/secrets/
|
|
27
|
+
docker cp secrets/.token-key gwo-worker:/home/gwo/.gwo/secrets/
|
|
28
|
+
docker cp secrets/oauth-client.json gwo-worker:/home/gwo/.gwo/secrets/
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
The key file is what protects the token; keep the pair together and nowhere else. On Windows the default store is DPAPI, which cannot be moved; that is why the login above forces AES.
|
|
32
|
+
4. **Check.** `docker exec gwo-worker node /opt/gwo/bin/gwo.js setup` prints the same status the chat tool shows; `docker exec gwo-worker node /opt/gwo/bin/gwo.js worker daily` runs once immediately.
|
|
33
|
+
|
|
34
|
+
## What the hosted worker does not do
|
|
35
|
+
|
|
36
|
+
It senses and escalates. Writes, triage and reports stay with the agent on a workstation, which reads the same state when it is a checkout or the same `~/.gwo` when installed. Two machines can share state only if the volume is shared; otherwise the workstation's scans and the host's scans are separate histories, which is fine for a sensing-only host.
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# התקנה: Google Web Operations
|
|
2
|
+
|
|
3
|
+
## דרישות
|
|
4
|
+
|
|
5
|
+
- Node 22.18 ומעלה (`node --version`)
|
|
6
|
+
- Claude Code ו/או Codex מותקנים
|
|
7
|
+
|
|
8
|
+
## 1. התקנה
|
|
9
|
+
|
|
10
|
+
```
|
|
11
|
+
npm i -g @aiguru/google-web-operations
|
|
12
|
+
gwo install
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
`gwo install` רושם את שרת ה‑MCP, את הסקילים ואת הפקודות בקלוד ובקודקס, ויוצר את `~/.gwo`. רק להוסט אחד: `gwo install claude` או `gwo install codex`. לראות בלי לשנות: `gwo install --print`.
|
|
16
|
+
|
|
17
|
+
חלופה בלי npm: להוריד את ה‑tgz מעמוד ה‑Releases בריפו ולהריץ `npm i -g ./aiguru-google-web-operations-<version>.tgz` (ה‑`./` חובה).
|
|
18
|
+
|
|
19
|
+
## 2. הפעלה מחדש ובדיקה
|
|
20
|
+
|
|
21
|
+
הפעלה מחדש של Claude Code ו‑Codex, ואז:
|
|
22
|
+
|
|
23
|
+
```
|
|
24
|
+
gwo doctor
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
הפלט אומר מה מוגדר, מה חסר, ומה הצעד הבא.
|
|
28
|
+
|
|
29
|
+
## 3. השיחה הראשונה
|
|
30
|
+
|
|
31
|
+
- Claude Code: `/gwo-setup`
|
|
32
|
+
- Codex: "הגדר את Google Web Operations"
|
|
33
|
+
|
|
34
|
+
הסוכן מוביל: חיבור לגוגל (לתת לו את הנתיב לקובץ ה‑JSON של לקוח ה‑OAuth, לא את התוכן), הסכמה בדפדפן עם חשבון התפעול, רישום אתר ראשון, ורשימת ההרשאות שהלקוח צריך לתת.
|
|
35
|
+
|
|
36
|
+
מחשב שני שאמור לראות את אותם אתרים: להעתיק את `sites/*.yaml` ל‑`~/.gwo/sites/`. ההסכמה לגוגל נעשית מחדש בכל מחשב (הטוקן קשור למשתמש).
|
|
37
|
+
|
|
38
|
+
## שדרוג
|
|
39
|
+
|
|
40
|
+
```
|
|
41
|
+
gwo update
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## הסרה
|
|
45
|
+
|
|
46
|
+
```
|
|
47
|
+
gwo uninstall
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
מסיר את הרישומים בהוסטים בלבד. `~/.gwo` נשארת.
|
|
51
|
+
|
|
52
|
+
## אופציונלי
|
|
53
|
+
|
|
54
|
+
- בדיקת DOM מרונדר (`web_inspect_rendered`): `npm i -g playwright && npx playwright install chromium`
|
|
55
|
+
- דוח לקוח בתבנית החברה: `GWO_DOCX_TEMPLATE` ב‑`~/.gwo/.env`
|
|
56
|
+
- משלוח דוחות במייל: `RESEND_API_KEY`, `GWO_REPORT_FROM`, `GWO_REPORT_TO`
|
|
57
|
+
- Pull requests לאתרי רפו: `GITHUB_TOKEN`
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
# Google Web Operations: Product and Technical Specification v0.2
|
|
2
|
+
|
|
3
|
+
Supersedes v0.1 (2026-09-18). v0.2 merges two independent v0.1 designs into one codebase: the skeleton, tooling and Google connectors from one, the crawl engine, rule set, snapshots, playbooks and policy enforcement from the other.
|
|
4
|
+
|
|
5
|
+
## 1. Purpose
|
|
6
|
+
|
|
7
|
+
Google Web Operations is an operational control layer for a portfolio of client websites. It continuously observes technical health, search visibility, AI answer-engine readiness and measurement instrumentation; turns observations into findings; and, within policy, prepares or executes remediation and verifies it.
|
|
8
|
+
|
|
9
|
+
It runs identically from Claude Code and Codex through one MCP server, and without any agent through a scheduled worker.
|
|
10
|
+
|
|
11
|
+
## 2. Principles
|
|
12
|
+
|
|
13
|
+
1. **One source of truth.** One repository, one long-lived branch, one operations core, one set of playbooks. Hosts are generated.
|
|
14
|
+
2. **Host-neutral.** Claude Code and Codex differences are packaging and instructions only.
|
|
15
|
+
3. **Observe before changing.** Every write is preceded by a read of current state.
|
|
16
|
+
4. **Policy before action.** Risk class is data, resolved before execution, and enforced in code. A prompt cannot lower it.
|
|
17
|
+
5. **Verify every write.** A write is complete when a fresh read shows the change. Not before.
|
|
18
|
+
6. **Auditability.** Every run and every write has a durable record with before, after and verification.
|
|
19
|
+
7. **No secret sprawl.** Site records carry references. Credentials live in gitignored secrets files and, in phase 2, an encrypted token store.
|
|
20
|
+
8. **Background-capable.** Sensing runs on a schedule without an interactive session. Deciding and acting need an agent.
|
|
21
|
+
9. **Bounded output.** Tools return summaries sized for a model's context. Full data stays on disk.
|
|
22
|
+
|
|
23
|
+
## 3. Scope of v0.2
|
|
24
|
+
|
|
25
|
+
### Delivered and verified
|
|
26
|
+
|
|
27
|
+
- Site registry (YAML, defaults, secrets merge, lookup by id or host).
|
|
28
|
+
- Policy engine: three risk classes, exact and prefix matching, site overrides that only tighten, token-gated enforcement.
|
|
29
|
+
- Storage: per-site scans, snapshots, snapshot diff, audit log.
|
|
30
|
+
- Web crawler: redirect chains, robots.txt with per-agent evaluation for 2 search and 14 AI crawlers, llms.txt, host-variant probe, sitemap and sitemap index, bounded-concurrency page fetch.
|
|
31
|
+
- Rule engine: 25 page rules and 17 site rules across indexability, metadata, structure, i18n, structured data, GEO, measurement, sitemap and performance.
|
|
32
|
+
- Google connectors with a swappable token provider: Search Console (performance summary with striking-distance list, raw query, sitemaps, URL inspection, sitemap submit), GA4 Data and Admin (traffic summary, raw report, realtime, key events, data streams), PageSpeed (summary with lab and field CWV).
|
|
33
|
+
- MCP server: 17 tools, underscore names, bounded outputs.
|
|
34
|
+
- Worker: daily/weekly/monthly sensing for all sites, audit-logged, non-zero exit on failure.
|
|
35
|
+
- CLI: sites, scan, inspect, diff, classify, audit.
|
|
36
|
+
- Seven playbooks, generated into Claude skills and commands and into Codex AGENTS.md.
|
|
37
|
+
- Tests for policy, registry, parser and rules. CI on push.
|
|
38
|
+
|
|
39
|
+
### v0.3 in progress
|
|
40
|
+
|
|
41
|
+
- **Durable Google OAuth: implemented, awaiting first consent.** Authorisation-code flow with PKCE and loopback redirect; refresh token encrypted at rest (DPAPI on Windows, AES-256-GCM elsewhere); silent refresh with in-memory cache; least-privilege default scopes with deliberate escalation per write capability; provider auto-selection (stored OAuth, else env bridge). CLI `auth login|status|logout`. Property discovery matches Search Console, GA4 and Tag Manager inventory to sites by host and applies ids to site YAML with `discover --apply`, preserving comments. MCP tools `google_auth_status` and `google_discover_properties`. Unit-tested: PKCE, both stores, refresh and cache, matching. The consent run itself needs `secrets/oauth-client.json` from the operator.
|
|
42
|
+
|
|
43
|
+
- **Live Google reads: verified** on both pilot sites through the stored authorisation with silent refresh: Search Console performance, sitemaps and URL inspection; GA4 data streams, traffic by channel, daily report, realtime and key events; PageSpeed mobile and desktop (attributed to the project via the OAuth token, since the keyless shared quota is unreliable).
|
|
44
|
+
- **The write loop: implemented and used.** `performWrite()` in core enforces policy, reads before, executes, reads after, verifies, and records before/after/verified. Blocked attempts are recorded too. First write built on it: `gsc_submit_sitemap` (policy `auto`), verified by `lastSubmitted` advancing in Search Console.
|
|
45
|
+
|
|
46
|
+
- **Tag Manager read: implemented.** Accounts, containers, workspaces, version headers, live version. Snapshots are shaped into a compact record (tags with resolved trigger names, paused state), persisted per site, and diffed to surface versions, tags, triggers and variables that changed. Tools `gtm_containers`, `gtm_versions`, `gtm_snapshot`, `gtm_diff`.
|
|
47
|
+
|
|
48
|
+
- **Site write adapters: implemented.** One interface (`ping`, `listPages`, `readPageSeo`, `writePageSeo`). Odoo over JSON-RPC with a dedicated API user and key, addressing `website.page` and `blog.post` SEO fields. Repository adapter over a `gwo.seo.json` manifest convention for sites AI Guru develops. Read tools `site_adapter_ping`, `site_pages`, `site_page_seo`; writes arrive in phase 5 through `performWrite()`. Tested against a fake JSON-RPC server and a temp checkout; no live Odoo client yet. See `docs/SITE-ADAPTERS.md`.
|
|
49
|
+
|
|
50
|
+
- **First content and configuration writes: implemented.** `content_set_meta_description` validates text by script (Hebrew 120 to 150 characters, Latin 70 to 160; no stuffing, HTML, breaks or caps), chooses the policy class from the stored value (empty field is `auto`, replacement is `approval_required`), applies through the site adapter inside the write loop and verifies by re-reading. `ga4_create_key_event` (approval required, idempotent) marks an event as a key event and verifies by listing. A content brief playbook (`gwo-content-brief`) encodes Hebrew SEO rules and answer-engine citation practices for the text the agent writes. Scan rules for description length are now script-aware.
|
|
51
|
+
|
|
52
|
+
### Deferred
|
|
53
|
+
|
|
54
|
+
- Tag Manager staged write and publish.
|
|
55
|
+
- Structured-data injection for Odoo pages (QWeb view edits).
|
|
56
|
+
- Title updates and JSON-LD writes through the adapters (the brief covers them; the tools follow the same loop).
|
|
57
|
+
- The first Google write, `ga4.key_event.create`.
|
|
58
|
+
- Cloudflare (cache purge, rules) and Resend (report delivery) connectors.
|
|
59
|
+
- Scheduled deployment and alerting.
|
|
60
|
+
- Client report rendering to a document.
|
|
61
|
+
|
|
62
|
+
## 4. Architecture
|
|
63
|
+
|
|
64
|
+
```
|
|
65
|
+
Claude Code ──┐
|
|
66
|
+
├── apps/mcp-server ──┐
|
|
67
|
+
Codex ────────┘ ├── packages/core ── connectors/web-crawler
|
|
68
|
+
│ │ connectors/google
|
|
69
|
+
apps/worker (cron) ─────────────────┤ ├── packages/policy
|
|
70
|
+
│ └── packages/storage
|
|
71
|
+
apps/cli ───────────────────────────┘
|
|
72
|
+
packages/playbooks ── tools/build-hosts ──> hosts/claude, hosts/codex
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
- `packages/core` owns the operations engine, registry, rule engine and types. It knows nothing about hosts.
|
|
76
|
+
- Connectors are pure I/O. No rules live in a connector.
|
|
77
|
+
- `packages/policy` is the only place execution can be refused.
|
|
78
|
+
- `packages/storage` is the only place state is written.
|
|
79
|
+
- `hosts/` is generated output. CI fails on a hand edit.
|
|
80
|
+
|
|
81
|
+
TypeScript runs natively on Node 22.18+ (type stripping). There is no build step and no runtime transpiler. Types are checked by `tsc --noEmit` in CI.
|
|
82
|
+
|
|
83
|
+
## 5. Operational loop
|
|
84
|
+
|
|
85
|
+
```
|
|
86
|
+
Observe -> Classify -> Authorise -> Execute -> Verify -> Record
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
On verification failure: rollback where the target supports it, escalate, record the failure.
|
|
90
|
+
|
|
91
|
+
## 6. Risk classes and enforcement
|
|
92
|
+
|
|
93
|
+
| Class | Meaning | Gate |
|
|
94
|
+
|---|---|---|
|
|
95
|
+
| `auto` | Read, analyse, report, or reversible with tiny blast radius | none |
|
|
96
|
+
| `approval_required` | Any content, schema, canonical, redirect, tag or configuration change | token `<site_id>:<action>` supplied in-session |
|
|
97
|
+
| `protected` | Deletion, account-level, retention, access, billing, legal, privacy | never |
|
|
98
|
+
|
|
99
|
+
`policies/default.yaml` is the source of truth. `packages/policy` resolves exact match over prefix match, most restrictive prefix wins, and site overrides may only raise a class. `enforce()` throws `PolicyError`; every write path must call it.
|
|
100
|
+
|
|
101
|
+
## 7. Schedules
|
|
102
|
+
|
|
103
|
+
| Cadence | Pages | What it looks for |
|
|
104
|
+
|---|---|---|
|
|
105
|
+
| Daily | 25 | Regressions since yesterday: status, noindex, canonical, tracking id, robots, sitemap size, host split, click drop |
|
|
106
|
+
| Weekly | 200 | Full findings list, striking-distance, decay, cannibalisation, CWV, verification of last week's fixes |
|
|
107
|
+
| Monthly | 200 | Structured data per template, GEO readiness, measurement hygiene, coverage, three-month trend, client report |
|
|
108
|
+
|
|
109
|
+
The worker performs the sensing half on schedule. An agent performs the deciding and acting half on demand or when triggered by the worker's output.
|
|
110
|
+
|
|
111
|
+
## 8. Tool surface (MCP)
|
|
112
|
+
|
|
113
|
+
| Tool | Class | Needs Google |
|
|
114
|
+
|---|---|---|
|
|
115
|
+
| `ops_list_sites`, `ops_get_site`, `ops_classify_action`, `ops_audit_log` | read | no |
|
|
116
|
+
| `web_scan_site`, `web_inspect_url`, `web_diff_scans` | read | no |
|
|
117
|
+
| `google_auth_status` | read | no |
|
|
118
|
+
| `gsc_performance`, `gsc_search_analytics`, `gsc_sitemaps`, `gsc_inspect_url` | read | yes |
|
|
119
|
+
| `ga4_traffic`, `ga4_run_report`, `ga4_realtime`, `ga4_key_events` | read | yes |
|
|
120
|
+
| `pagespeed_check` | read | optional key |
|
|
121
|
+
| `gsc_submit_sitemap` | write, `auto` | yes |
|
|
122
|
+
| `gtm_containers`, `gtm_versions`, `gtm_snapshot`, `gtm_diff` | read | yes |
|
|
123
|
+
| `site_adapter_ping`, `site_pages`, `site_page_seo` | read | no (site credentials) |
|
|
124
|
+
| `content_set_meta_description` | write, `auto` when empty, else `approval_required` | no (site credentials) |
|
|
125
|
+
| `ga4_create_key_event` | write, `approval_required` | yes, `analytics.edit` |
|
|
126
|
+
|
|
127
|
+
Future write tools are narrow and named for one effect: `ga4_create_key_event`, `content_update_meta_description`, never `google_change_setting`.
|
|
128
|
+
|
|
129
|
+
## 9. Data model
|
|
130
|
+
|
|
131
|
+
- `sites/<host>.yaml`: registry record, schema in `sites/schema.yaml`.
|
|
132
|
+
- `.gwo-data/<site_id>/latest-scan.json`: last full scan.
|
|
133
|
+
- `.gwo-data/<site_id>/snapshots/<ts>.json`: fingerprints for diffing.
|
|
134
|
+
- `.gwo-data/<site_id>/audit.jsonl`: one record per run, proposal, write or block. Writes carry `before`, `after`, `verified`.
|
|
135
|
+
|
|
136
|
+
## 10. Security
|
|
137
|
+
|
|
138
|
+
See `docs/SECURITY.md`. In short: no credentials in the registry or the repository; stdout of the MCP process is protocol-only; visitor PII never passes through this system; every write is policy-gated, recorded and verified.
|
|
139
|
+
|
|
140
|
+
## 11. Pilot success criteria
|
|
141
|
+
|
|
142
|
+
For `doritgrinberg.co.il` and `aiguru.co.il`, v0.2 is operational when:
|
|
143
|
+
|
|
144
|
+
1. `npm run check` passes locally and in CI.
|
|
145
|
+
2. `web_scan_site` returns findings for both sites from both hosts.
|
|
146
|
+
3. The worker records a daily run for both sites.
|
|
147
|
+
4. With a token configured, `gsc_performance` and `ga4_traffic` return live data.
|
|
148
|
+
|
|
149
|
+
Items 1 to 3 are met at the time of writing. Item 4 waits on Google access.
|
|
150
|
+
|
|
151
|
+
## 12. v0.3 target
|
|
152
|
+
|
|
153
|
+
Durable OAuth and property discovery; Tag Manager read; Odoo and repository write adapters; `ga4_create_key_event` as the first verified write; scheduled worker deployment with alerting.
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
# Google Web Operations: Product and Technical Specification v0.3
|
|
2
|
+
|
|
3
|
+
Supersedes v0.2 (kept for history). v0.3 completes the six-step plan: durable Google access, live reads, Tag Manager read, site write adapters, the first verified writes, and scheduled operation with delivery.
|
|
4
|
+
|
|
5
|
+
## 1. Purpose
|
|
6
|
+
|
|
7
|
+
Google Web Operations is an operational control layer for a portfolio of client websites. It observes technical health, search visibility, answer-engine readiness and measurement; turns observations into ranked findings; decides against playbooks; acts within a strict permission model; verifies every write; and records everything. It runs identically from Claude Code and Codex through one MCP server, and its sensing half runs on a schedule without any agent.
|
|
8
|
+
|
|
9
|
+
## 2. Principles
|
|
10
|
+
|
|
11
|
+
Unchanged from v0.2: one source of truth, host-neutral, observe before changing, policy before action, verify every write, auditability, no secret sprawl, background-capable, bounded output.
|
|
12
|
+
|
|
13
|
+
## 3. What v0.3 delivers
|
|
14
|
+
|
|
15
|
+
| Area | Delivered |
|
|
16
|
+
|---|---|
|
|
17
|
+
| Google access | Authorisation-code OAuth with PKCE and loopback; refresh token encrypted at rest (DPAPI on Windows, AES-GCM elsewhere); silent refresh; least-privilege default scopes with explicit escalation per write capability; property discovery that fills site files |
|
|
18
|
+
| Reads | Search Console (performance summary with striking distance, raw query, sitemaps, URL inspection), GA4 (streams, traffic, daily report, realtime, key events), PageSpeed (attributed to the project), Tag Manager (accounts, containers, versions, live-version snapshot and diff) |
|
|
19
|
+
| Site adapters | One interface; Odoo over JSON-RPC with a dedicated API user (`website.page`, `blog.post`); repository manifest `gwo.seo.json` for sites AI Guru develops |
|
|
20
|
+
| Writes | The write loop `performWrite()`: enforce, read before, execute, read after, verify, record. Users: `gsc_submit_sitemap` (auto), `content_set_meta_description` (auto when empty, approval otherwise, validated per the content brief), `ga4_create_key_event` (approval, idempotent), `repo_open_pr` (approval, idempotent per day) |
|
|
21
|
+
| Content | `gwo-content-brief` playbook: Hebrew SEO rules and answer-engine citation practices; scan rules aware of Hebrew vs Latin description lengths |
|
|
22
|
+
| Scheduling | Worker with escalation rules in code (page broken, noindex gained, canonical lost, tracking lost, host split, crawler blocked, sitemap shrunk or unreachable), a written report per run, exit codes for schedulers, optional email delivery through Resend, Windows Task Scheduler installer |
|
|
23
|
+
| Hosts | Claude Code plugin (8 skills, 6 commands) and Codex (AGENTS.md, config template) generated from one playbook set; CI fails on a hand edit |
|
|
24
|
+
| Quality | Typecheck, unit tests for every pure module and every write path (with fakes), smoke test of the MCP server; CI on push |
|
|
25
|
+
|
|
26
|
+
## 4. Architecture
|
|
27
|
+
|
|
28
|
+
```
|
|
29
|
+
Claude Code ──┐
|
|
30
|
+
├── apps/mcp-server ──┐
|
|
31
|
+
Codex ────────┘ │
|
|
32
|
+
apps/worker (Task Scheduler) ───────┼── packages/core ── connectors/{web-crawler, google, odoo, repo, github, resend}
|
|
33
|
+
apps/cli ───────────────────────────┘ ├── packages/policy
|
|
34
|
+
└── packages/storage
|
|
35
|
+
packages/playbooks ── tools/build-hosts ──> hosts/claude, hosts/codex
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
TypeScript executed natively by Node 22.18+. No build step. `tsc --noEmit` in CI.
|
|
39
|
+
|
|
40
|
+
## 5. Operational loop
|
|
41
|
+
|
|
42
|
+
```
|
|
43
|
+
Observe -> Classify -> Authorise -> Execute -> Verify -> Record
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Every write goes through `performWrite()`. A write whose verification fails is a failed write. Blocked attempts are recorded.
|
|
47
|
+
|
|
48
|
+
## 6. Risk classes
|
|
49
|
+
|
|
50
|
+
| Class | Gate |
|
|
51
|
+
|---|---|
|
|
52
|
+
| `auto` | none |
|
|
53
|
+
| `approval_required` | token `<site_id>:<action>` in-session |
|
|
54
|
+
| `protected` | never |
|
|
55
|
+
|
|
56
|
+
`policies/default.yaml`; site overrides may only tighten.
|
|
57
|
+
|
|
58
|
+
## 7. Schedules
|
|
59
|
+
|
|
60
|
+
| Cadence | Pages | Worker does | Agent does |
|
|
61
|
+
|---|---|---|---|
|
|
62
|
+
| Daily 07:00 | 25 | scan, diff, escalate, report, deliver | triage anything escalated |
|
|
63
|
+
| Weekly Monday 07:30 | 200 | scan, diff, escalate, report, deliver | the weekly improvement pass |
|
|
64
|
+
| Monthly | 200 | on demand | deep scan and client report |
|
|
65
|
+
|
|
66
|
+
Exit codes: 0 healthy, 2 escalations, 1 failures.
|
|
67
|
+
|
|
68
|
+
## 8. Tool surface
|
|
69
|
+
|
|
70
|
+
29 tools. Reads: `ops_*`, `web_*`, `google_*`, `gsc_*`, `ga4_*`, `gtm_*`, `site_*`, `pagespeed_check`. Writes: `gsc_submit_sitemap`, `content_set_meta_description`, `ga4_create_key_event`, `repo_open_pr`.
|
|
71
|
+
|
|
72
|
+
## 9. Data model
|
|
73
|
+
|
|
74
|
+
`sites/<host>.yaml` and gitignored `<host>.secrets.yaml`; `.gwo-data/<site_id>/{latest-scan.json, snapshots/, gtm/, audit.jsonl}`; `.gwo-data/_runs/` for worker reports; `secrets/` for the OAuth client and token.
|
|
75
|
+
|
|
76
|
+
## 10. Security
|
|
77
|
+
|
|
78
|
+
See `docs/SECURITY.md`. Additions in v0.3: Resend and GitHub tokens by environment only; scheduled tasks run as the operator's Windows user because the token store is DPAPI-bound; the GitHub token is fine-grained and scoped to the site repositories.
|
|
79
|
+
|
|
80
|
+
## 11. Pilot status
|
|
81
|
+
|
|
82
|
+
Both pilot sites (`aiguru.co.il`, `doritgrinberg.co.il`) are scanned daily, their Google properties are read live, and the first verified write (sitemap submission for aiguru) is in the audit log. Both are at near-zero organic traffic; operations on them is building presence, not optimising it. Pending on the operator: `analytics.edit` consent for the key-event write; `local_path` plus `gwo.seo.json` for content writes; Resend and GitHub tokens for delivery and pull requests.
|
|
83
|
+
|
|
84
|
+
## 12. v0.4 targets
|
|
85
|
+
|
|
86
|
+
Tag Manager staged writes in a dedicated workspace with diff and approval-gated publish; title and JSON-LD writes through the adapters; Odoo structured-data injection; client report rendering to a document; an accessibility rule area (IS 5568) in the scanner; rendered-DOM checks with Playwright for JavaScript-heavy sites; a hosted worker so operations do not depend on one machine.
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
# Google Web Operations: Product and Technical Specification v0.4
|
|
2
|
+
|
|
3
|
+
Supersedes v0.3 (kept for history). v0.4 adds the write capabilities the playbooks were already asking for: Tag Manager changes staged, diffed and published under two gates; titles and structured data written through the site adapters; and a measurement playbook that tells both hosts how to use them.
|
|
4
|
+
|
|
5
|
+
## 1. Purpose
|
|
6
|
+
|
|
7
|
+
Google Web Operations is an operational control layer for a portfolio of client websites. It observes technical health, search visibility, answer-engine readiness and measurement; turns observations into ranked findings; decides against playbooks; acts within a strict permission model; verifies every write; and records everything. It runs identically from Claude Code and Codex through one MCP server, and its sensing half runs on a schedule without any agent.
|
|
8
|
+
|
|
9
|
+
## 2. Principles
|
|
10
|
+
|
|
11
|
+
Unchanged from v0.2: one source of truth, host-neutral, observe before changing, policy before action, verify every write, auditability, no secret sprawl, background-capable, bounded output.
|
|
12
|
+
|
|
13
|
+
New in v0.4: **a set of changes is reviewed as a set.** Where a write's effect is a bundle rather than one value (a container version), the operator's approval alone is not enough; the write also carries a token derived from the exact bundle that was shown (ADR-005).
|
|
14
|
+
|
|
15
|
+
## 3. What v0.4 delivers
|
|
16
|
+
|
|
17
|
+
| Area | Delivered |
|
|
18
|
+
|---|---|
|
|
19
|
+
| Tag Manager writes | Workspace creation under the policy prefix; `gtm_stage` writes tags, triggers and variables one verified write each (create, or merge-update by name; trigger names resolve to ids; triggers before tags); `gtm_workspace_diff` shapes GTM's own change list against the live version and derives a review token; `gtm_publish` syncs, re-checks the token, creates the version, publishes, verifies the live version id, and snapshots. `gtm_workspaces` shows staged and client-owned work |
|
|
20
|
+
| Content writes | `content_set_title` (approval always, validated: 15 to 65 characters, one separator, no repeated term); `content_set_schema` (approval always, validated: schema.org context and type, FAQ shape, no script break, 20 KB cap; empty list removes); `site_page_schema` reads managed blocks next to what the live page emits |
|
|
21
|
+
| Adapters | `readPageSchema` / `writePageSchema` on the adapter interface. Repository: `schema` array in the manifest entry. Odoo: one marked `<script type="application/ld+json" data-gwo="schema">` in the page view's arch (before `#wrap`, outside the editor-owned structure) or appended to a blog post's content; XML-safe serialisation; other scripts never touched |
|
|
22
|
+
| Site decisions | `findings.suppress` in the site file: rule (exact or `area.*`), optional path (exact or prefix), reason. Applied after the rules run; suppressed findings are counted per rule in the scan header and audit log, never hidden. Added after the first developer review of a pilot site, where GA4-without-GTM and a short contact page were deliberate |
|
|
23
|
+
| Setup from chat | `ops_setup_status` (one read: OAuth client, authorised account and scopes, write scopes, .env settings, per-site configuration and what is missing, next steps), `google_setup_oauth_client` (installs the downloaded Desktop-app JSON by path; contents never pass through chat), `google_auth_login` (consent flow from the host, waits ~90 s then continues in the background), `google_discover_apply`, `ops_add_site` (standard site file from url, name, platform), `ops_update_site` (dotted path, comments kept; site_id, policy and credentials refused), `ops_add_suppression`. All classed `auto` as this system's own configuration and recorded in the audit log. New `gwo-setup` skill and `/gwo-setup`, `/gwo-add-site` commands |
|
|
24
|
+
| Client report | `report_client_monthly`: collects Search Console and GA4 totals for the month and the previous one, scan health now and a month ago, and the month's audit activity; composes the client document (Hebrew or English) per the report template with the agent's narrative on top; writes a .docx inside the company template (`GWO_DOCX_TEMPLATE`, header, footer and styles inherited, body replaced) or a standalone styled package, plus a Markdown twin. RTL by paragraph, run and table. Own OOXML writer over jszip; no other dependency |
|
|
25
|
+
| Playbooks | New `gwo-measurement`: the standard stack per client, the audit, the stage-diff-publish protocol, entity bodies, key events, what to do when the client publishes. Weekly, daily, triage, onboarding and the content brief updated to name the new tools and their gates. Operating model gains a tools-by-intent table |
|
|
26
|
+
| Hosts | 10 skills and 9 commands (`/gwo-measure`, `/gwo-setup`, `/gwo-add-site` added) for Claude Code; the same 10 skills for Codex; both generated |
|
|
27
|
+
| Quality | 81 tests: setup and registry administration, GTM pure helpers, suppressions, report composition (no jargon leaks), the Word writer standalone and inside the template, a fake Tag Manager API exercising blocked, staged, merged, stale-token and successful publish paths; title and schema validators and writes; Odoo arch injection and blog injection; repo schema round trip |
|
|
28
|
+
|
|
29
|
+
Carried from v0.3 unchanged: OAuth with encrypted refresh token, Search Console, GA4, PageSpeed and Tag Manager reads, meta-description writes, key events, sitemap submission, pull requests, the scheduled worker with escalation and delivery, CI.
|
|
30
|
+
|
|
31
|
+
## 4. Architecture
|
|
32
|
+
|
|
33
|
+
```
|
|
34
|
+
Claude Code ──┐
|
|
35
|
+
├── apps/mcp-server ──┐
|
|
36
|
+
Codex ────────┘ │
|
|
37
|
+
apps/worker (Task Scheduler) ───────┼── packages/core ── connectors/{web-crawler, google, odoo, repo, github, resend}
|
|
38
|
+
apps/cli ───────────────────────────┘ ├── packages/policy
|
|
39
|
+
└── packages/storage
|
|
40
|
+
packages/playbooks ── tools/build-hosts ──> hosts/claude, hosts/codex
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
`packages/core/src/gtm-ops.ts` holds every Tag Manager operation, read and write; `content.ts` holds the three content writes and their validators; `report/monthly.ts` the client report; `connectors/docx` the Word writer. TypeScript executed natively by Node 22.18+. No build step. `tsc --noEmit` in CI.
|
|
44
|
+
|
|
45
|
+
## 5. Operational loop
|
|
46
|
+
|
|
47
|
+
```
|
|
48
|
+
Observe -> Classify -> Authorise -> Execute -> Verify -> Record
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Every write goes through `performWrite()`. A write whose verification fails is a failed write. Blocked attempts are recorded. For a container publish, "Authorise" is two tokens.
|
|
52
|
+
|
|
53
|
+
## 6. Risk classes
|
|
54
|
+
|
|
55
|
+
| Class | Gate |
|
|
56
|
+
|---|---|
|
|
57
|
+
| `auto` | none |
|
|
58
|
+
| `approval_required` | token `<site_id>:<action>` in-session |
|
|
59
|
+
| `approval_required` + review | the above plus the review token of the reviewed diff (`gtm.publish`) |
|
|
60
|
+
| `protected` | never |
|
|
61
|
+
|
|
62
|
+
`policies/default.yaml`; site overrides may only tighten. No policy ids were added in v0.4: `gtm.stage`, `gtm.publish`, `content.title.update` and `content.schema.update` were already listed and are now implemented.
|
|
63
|
+
|
|
64
|
+
## 7. Schedules
|
|
65
|
+
|
|
66
|
+
| Cadence | Pages | Worker does | Agent does |
|
|
67
|
+
|---|---|---|---|
|
|
68
|
+
| Daily 07:00 | 25 | scan, diff, escalate, report, deliver | triage anything escalated |
|
|
69
|
+
| Weekly Monday 07:30 | 200 | scan, diff, escalate, report, deliver | the weekly improvement pass |
|
|
70
|
+
| Monthly | 200 | on demand | deep scan and client report |
|
|
71
|
+
|
|
72
|
+
Exit codes: 0 healthy, 2 escalations, 1 failures.
|
|
73
|
+
|
|
74
|
+
## 8. Tool surface
|
|
75
|
+
|
|
76
|
+
44 tools. Setup: `ops_setup_status`, `google_setup_oauth_client`, `google_auth_login`, `google_discover_apply`, `ops_add_site`, `ops_update_site`, `ops_add_suppression`. Reads: `report_client_monthly` (writes files under `.gwo-data`, not to any site), `ops_*`, `web_*`, `google_*`, `gsc_*`, `ga4_*`, `gtm_containers`, `gtm_versions`, `gtm_snapshot`, `gtm_diff`, `gtm_workspaces`, `gtm_workspace_diff`, `site_*`, `pagespeed_check`. Writes: `gsc_submit_sitemap`, `content_set_meta_description`, `content_set_title`, `content_set_schema`, `ga4_create_key_event`, `gtm_stage`, `gtm_publish`, `repo_open_pr`.
|
|
77
|
+
|
|
78
|
+
## 9. Data model
|
|
79
|
+
|
|
80
|
+
`sites/<host>.yaml` and gitignored `<host>.secrets.yaml`; `.gwo-data/<site_id>/{latest-scan.json, snapshots/, gtm/, gtm-stage/, audit.jsonl}`; `.gwo-data/_runs/` for worker reports; `secrets/` for the OAuth client and token. `gtm-stage/` keeps each staging result with its diff and review token for the record; the gate itself recomputes from live state and never trusts the file.
|
|
81
|
+
|
|
82
|
+
## 10. Security
|
|
83
|
+
|
|
84
|
+
See `docs/SECURITY.md`. Additions in v0.4: Tag Manager edit and publish scopes are still opt-in (`auth login --scope gtm_edit`, `--scope gtm_publish`); the Odoo API user needs view-editing rights only for structured data, and the adapter edits one marked element; the review token is derived from server state and cannot be forged from a stale diff.
|
|
85
|
+
|
|
86
|
+
## 11. Pilot status
|
|
87
|
+
|
|
88
|
+
Both pilot sites are scanned daily and read live. Neither has a Tag Manager container registered yet (`google.tag_manager.public_id` is null), so the staged-write path is verified against a fake API and awaits a container. aiguru is being fixed by hand in parallel and is out of scope for agent writes this cycle. Pending on the operator: `analytics.edit` consent for the key-event write; `local_path` plus `gwo.seo.json` for content writes; Resend and GitHub tokens; a container id per site.
|
|
89
|
+
|
|
90
|
+
## 12. v0.5 targets
|
|
91
|
+
|
|
92
|
+
An accessibility rule area (IS 5568) in the scanner; rendered-DOM checks with Playwright for JavaScript-heavy sites; a hosted worker so operations do not depend on one machine; product pages in the Odoo adapter when a client needs them.
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
# Google Web Operations: Product and Technical Specification v0.5
|
|
2
|
+
|
|
3
|
+
Supersedes v0.4 (kept for history). v0.5 makes the system installable: one npm package, one `gwo install` for both hosts, operator state outside the package. It also carries what landed after v0.4 was written: setup and site administration from the chat, the monthly client report as a Word document, and per-site decisions the scanner respects.
|
|
4
|
+
|
|
5
|
+
## 1. Purpose
|
|
6
|
+
|
|
7
|
+
Google Web Operations is an operational control layer for a portfolio of client websites. It observes technical health, search visibility, answer-engine readiness and measurement; turns observations into ranked findings; decides against playbooks; acts within a strict permission model; verifies every write; and records everything. It runs identically from Claude Code and Codex through one MCP server, and its sensing half runs on a schedule without any agent.
|
|
8
|
+
|
|
9
|
+
## 2. Principles
|
|
10
|
+
|
|
11
|
+
Unchanged from v0.2: one source of truth, host-neutral, observe before changing, policy before action, verify every write, auditability, no secret sprawl, background-capable, bounded output.
|
|
12
|
+
|
|
13
|
+
New in v0.4: **a set of changes is reviewed as a set.** Where a write's effect is a bundle rather than one value (a container version), the operator's approval alone is not enough; the write also carries a token derived from the exact bundle that was shown (ADR-005).
|
|
14
|
+
|
|
15
|
+
## 3. What v0.5 delivers (cumulative since v0.3)
|
|
16
|
+
|
|
17
|
+
| Area | Delivered |
|
|
18
|
+
|---|---|
|
|
19
|
+
| Distribution | npm package `@aiguru/google-web-operations` on GitHub Packages (`npm i -g @aiguru/google-web-operations`, `gwo update` for the latest release; a token with read:packages once per machine) with the `gwo` executable: `gwo install [claude\|codex\|all]` writes the user-scope MCP server (absolute node and package paths), skills and slash commands for Claude Code (`~/.claude.json`, `~/.claude/skills`, `~/.claude/commands`) and the MCP block and skills for Codex (`~/.codex/config.toml`, `~/.codex/skills`); idempotent, `uninstall` removes only `gwo-*` entries. State in `GWO_HOME` (default `~/.gwo`: sites, .gwo-data, secrets, .env, optional policy); a checkout keeps state next to the code. The package ships compiled JavaScript (`tools/build-package.ts`, tsc with rewritten `.ts` imports) because Node does not strip types under `node_modules`; development stays native TypeScript. `npm run check` builds and runs the packaged bin. Release workflow packs a tarball on `v*` tags (ADR-006) |
|
|
20
|
+
| Accessibility (IS 5568) | New `accessibility` rule area from static HTML (`packages/connectors/web-crawler/src/a11y.ts`): unlabelled form fields (high), unnamed buttons, empty and generic links, untitled iframes, blocked pinch zoom, skipped heading levels, positive tabindex, duplicate ids, autoplay media, missing main landmark, missing skip link; site-wide `a11y.statement.missing` (high, the Israeli legal requirement). Contrast, keyboard behaviour and PDFs are declared out of scope in the monthly playbook |
|
|
21
|
+
| Tag Manager writes | Workspace creation under the policy prefix; `gtm_stage` writes tags, triggers and variables one verified write each (create, or merge-update by name; trigger names resolve to ids; triggers before tags); `gtm_workspace_diff` shapes GTM's own change list against the live version and derives a review token; `gtm_publish` syncs, re-checks the token, creates the version, publishes, verifies the live version id, and snapshots. `gtm_workspaces` shows staged and client-owned work |
|
|
22
|
+
| Content writes | `content_set_title` (approval always, validated: 15 to 65 characters, one separator, no repeated term); `content_set_schema` (approval always, validated: schema.org context and type, FAQ shape, no script break, 20 KB cap; empty list removes); `site_page_schema` reads managed blocks next to what the live page emits |
|
|
23
|
+
| Adapters | `readPageSchema` / `writePageSchema` on the adapter interface. Repository: `schema` array in the manifest entry. Odoo: one marked `<script type="application/ld+json" data-gwo="schema">` in the page view's arch (before `#wrap`, outside the editor-owned structure) or appended to a blog post's content; XML-safe serialisation; other scripts never touched |
|
|
24
|
+
| Site decisions | `findings.suppress` in the site file: rule (exact or `area.*`), optional path (exact or prefix), reason. Applied after the rules run; suppressed findings are counted per rule in the scan header and audit log, never hidden. Added after the first developer review of a pilot site, where GA4-without-GTM and a short contact page were deliberate |
|
|
25
|
+
| Setup from chat | `ops_setup_status` (one read: OAuth client, authorised account and scopes, write scopes, .env settings, per-site configuration and what is missing, next steps), `google_setup_oauth_client` (installs the downloaded Desktop-app JSON by path; contents never pass through chat), `google_auth_login` (consent flow from the host, waits ~90 s then continues in the background), `google_discover_apply`, `ops_add_site` (standard site file from url, name, platform), `ops_update_site` (dotted path, comments kept; site_id, policy and credentials refused), `ops_add_suppression`. All classed `auto` as this system's own configuration and recorded in the audit log. New `gwo-setup` skill and `/gwo-setup`, `/gwo-add-site` commands |
|
|
26
|
+
| Client report | `report_client_monthly`: collects Search Console and GA4 totals for the month and the previous one, scan health now and a month ago, and the month's audit activity; composes the client document (Hebrew or English) per the report template with the agent's narrative on top; writes a .docx inside the company template (`GWO_DOCX_TEMPLATE`, header, footer and styles inherited, body replaced) or a standalone styled package, plus a Markdown twin. RTL by paragraph, run and table. Own OOXML writer over jszip; no other dependency |
|
|
27
|
+
| Playbooks | New `gwo-measurement`: the standard stack per client, the audit, the stage-diff-publish protocol, entity bodies, key events, what to do when the client publishes. Weekly, daily, triage, onboarding and the content brief updated to name the new tools and their gates. Operating model gains a tools-by-intent table |
|
|
28
|
+
| Hosts | Installed by `gwo install` from the generated `hosts/` tree; 10 skills and 9 commands (`/gwo-measure`, `/gwo-setup`, `/gwo-add-site` added) for Claude Code; the same 10 skills for Codex; both generated |
|
|
29
|
+
| Quality | 89 tests: accessibility parsing and rules, path resolution and the installer against temporary homes, setup and registry administration, GTM pure helpers, suppressions, report composition (no jargon leaks), the Word writer standalone and inside the template, a fake Tag Manager API exercising blocked, staged, merged, stale-token and successful publish paths; title and schema validators and writes; Odoo arch injection and blog injection; repo schema round trip |
|
|
30
|
+
|
|
31
|
+
Carried from v0.3 unchanged: OAuth with encrypted refresh token, Search Console, GA4, PageSpeed and Tag Manager reads, meta-description writes, key events, sitemap submission, pull requests, the scheduled worker with escalation and delivery, CI.
|
|
32
|
+
|
|
33
|
+
## 4. Architecture
|
|
34
|
+
|
|
35
|
+
```
|
|
36
|
+
Claude Code ──┐
|
|
37
|
+
├── apps/mcp-server ──┐
|
|
38
|
+
Codex ────────┘ │
|
|
39
|
+
apps/worker (Task Scheduler) ───────┼── packages/core ── connectors/{web-crawler, google, odoo, repo, github, resend}
|
|
40
|
+
apps/cli ───────────────────────────┘ ├── packages/policy
|
|
41
|
+
└── packages/storage
|
|
42
|
+
packages/playbooks ── tools/build-hosts ──> hosts/claude, hosts/codex
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
`bin/gwo.js` dispatches to the MCP server, worker, installer or CLI. `packages/core/src/paths.ts` decides checkout versus installed layout. `packages/core/src/gtm-ops.ts` holds every Tag Manager operation, read and write; `content.ts` holds the three content writes and their validators; `report/monthly.ts` the client report; `connectors/docx` the Word writer. TypeScript executed natively by Node 22.18+. No build step. `tsc --noEmit` in CI.
|
|
46
|
+
|
|
47
|
+
## 5. Operational loop
|
|
48
|
+
|
|
49
|
+
```
|
|
50
|
+
Observe -> Classify -> Authorise -> Execute -> Verify -> Record
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Every write goes through `performWrite()`. A write whose verification fails is a failed write. Blocked attempts are recorded. For a container publish, "Authorise" is two tokens.
|
|
54
|
+
|
|
55
|
+
## 6. Risk classes
|
|
56
|
+
|
|
57
|
+
| Class | Gate |
|
|
58
|
+
|---|---|
|
|
59
|
+
| `auto` | none |
|
|
60
|
+
| `approval_required` | token `<site_id>:<action>` in-session |
|
|
61
|
+
| `approval_required` + review | the above plus the review token of the reviewed diff (`gtm.publish`) |
|
|
62
|
+
| `protected` | never |
|
|
63
|
+
|
|
64
|
+
`policies/default.yaml`; site overrides may only tighten. No policy ids were added in v0.4: `gtm.stage`, `gtm.publish`, `content.title.update` and `content.schema.update` were already listed and are now implemented.
|
|
65
|
+
|
|
66
|
+
## 7. Schedules
|
|
67
|
+
|
|
68
|
+
| Cadence | Pages | Worker does | Agent does |
|
|
69
|
+
|---|---|---|---|
|
|
70
|
+
| Daily 07:00 | 25 | scan, diff, escalate, report, deliver | triage anything escalated |
|
|
71
|
+
| Weekly Monday 07:30 | 200 | scan, diff, escalate, report, deliver | the weekly improvement pass |
|
|
72
|
+
| Monthly | 200 | on demand | deep scan and client report |
|
|
73
|
+
|
|
74
|
+
Exit codes: 0 healthy, 2 escalations, 1 failures.
|
|
75
|
+
|
|
76
|
+
## 8. Tool surface
|
|
77
|
+
|
|
78
|
+
44 tools. Setup: `ops_setup_status`, `google_setup_oauth_client`, `google_auth_login`, `google_discover_apply`, `ops_add_site`, `ops_update_site`, `ops_add_suppression`. Reads: `report_client_monthly` (writes files under `.gwo-data`, not to any site), `ops_*`, `web_*`, `google_*`, `gsc_*`, `ga4_*`, `gtm_containers`, `gtm_versions`, `gtm_snapshot`, `gtm_diff`, `gtm_workspaces`, `gtm_workspace_diff`, `site_*`, `pagespeed_check`. Writes: `gsc_submit_sitemap`, `content_set_meta_description`, `content_set_title`, `content_set_schema`, `ga4_create_key_event`, `gtm_stage`, `gtm_publish`, `repo_open_pr`.
|
|
79
|
+
|
|
80
|
+
## 9. Data model
|
|
81
|
+
|
|
82
|
+
Under `GWO_HOME` (the checkout itself, or `~/.gwo`): `sites/<host>.yaml` and gitignored `<host>.secrets.yaml`; `.gwo-data/<site_id>/{latest-scan.json, snapshots/, gtm/, gtm-stage/, audit.jsonl}`; `.gwo-data/_runs/` for worker reports; `secrets/` for the OAuth client and token. `gtm-stage/` keeps each staging result with its diff and review token for the record; the gate itself recomputes from live state and never trusts the file.
|
|
83
|
+
|
|
84
|
+
## 10. Security
|
|
85
|
+
|
|
86
|
+
See `docs/SECURITY.md`. Additions in v0.4: Tag Manager edit and publish scopes are still opt-in (`auth login --scope gtm_edit`, `--scope gtm_publish`); the Odoo API user needs view-editing rights only for structured data, and the adapter edits one marked element; the review token is derived from server state and cannot be forged from a stale diff.
|
|
87
|
+
|
|
88
|
+
## 11. Pilot status
|
|
89
|
+
|
|
90
|
+
Both pilot sites are scanned daily and read live. Neither has a Tag Manager container registered yet (`google.tag_manager.public_id` is null), so the staged-write path is verified against a fake API and awaits a container. aiguru is being fixed by hand in parallel and is out of scope for agent writes this cycle. Pending on the operator: `analytics.edit` consent for the key-event write; `local_path` plus `gwo.seo.json` for content writes; Resend and GitHub tokens; a container id per site.
|
|
91
|
+
|
|
92
|
+
## 12. v0.6 targets
|
|
93
|
+
|
|
94
|
+
Rendered-DOM checks with Playwright for JavaScript-heavy sites; a hosted worker so operations do not depend on one machine; product pages in the Odoo adapter when a client needs them.
|