- name
- devrel-frictionlog-codelab
- version
- 0.3.5
- description
- 🥑 [DevRel] Automates friction logging for Google Codelabs (v2.0) with multi-instance collision guards, reentrant gcloud configs, pre-teardown UAT gates, and deterministic telemetry.
# DevRel Friction Log Codelab
This skill automates the process of going through a Google Codelab, reproducing its steps, systematically documenting the experience (a "friction log"), identifying bugs in external repositories, and producing actionable reports.
## 🚫 Golden Rules
### 1. Commit Hook Progression (Never Run 2 FLs on the Same Commit!)
* **Do NOT run multiple Friction Log iterations (`FL001`, `FL002`, ...) against the exact same unpatched Commit SHA (`X`)!**
* Every Friction Log iteration (`FLXXX`) must record the exact **Git Commit SHA and Commit Timestamp** (`git log -1 --format="%h (%ci)"`) of the repository/codelab being tested (`REPO_COMMIT_HOOK`).
* The mandatory iterative cycle is:
1. Run **`FL001`** on initial commit `X` (recording Commit SHA `X` + its timestamp).
2. Log all defects in `BUGS.md`, open a **GitHub/GitLab Issue (GHI/GLI)** or **Buganizer bug** tagged with `friction-log` and `FL001`.
3. Create a **Pull Request / Merge Request (PR/MR)** attached to the issue (`Fixes #N`), review/test it, and **merge** it into `main` to produce a new Commit SHA `Y`.
4. Run **`FL002`** on the new commit `Y` to verify fixes and iterate until the scorecard is **100% 🟢 GREEN**.
### 2. Buganizer Hotlist Mandate (`#8950858`)
* **Whenever you create or update a Buganizer issue (`b/<BUG_ID>`) during a Friction Log campaign, you MUST tag the bug with hotlist `#8950858` (`HOTLIST+=8950858`)!**
* Note on `bugged` CLI: If `bugged` blocks AI agents (`bugged is not suitable for AI agents`), invoke it with a clean environment and place bugspec tags at the very bottom of stdin:
```bash
echo -e "Friction Log update summary...\n\nHOTLIST+=8950858" | env -i PATH="$PATH" HOME="$HOME" USER="$USER" bugged edit <BUG_ID>
```
### 3. Virgin Local Baseline & Virgin GCP Project Mandate
* **Always reproduce from a clean, virgin local baseline:** Run reproduction in a dedicated clean directory, worktree, or fresh clone representing the exact student baseline (`git checkout main` or release tag).
* **Always use a brand-new, virgin GCP Project:** A Friction Log MUST start on a clean, empty GCP project with **zero pre-enabled APIs and zero pre-existing resources**. Never recycle dirty projects or previously deployed resources (e.g. leftover Cloud SQL instances or GCS buckets) from previous runs!
* Assign a **different dedicated GCP Project** (e.g. from the 90-day pool `011F17-0F9CE4-E03264`) to each iteration (`FL001`, `FL002`, `FL003`) to guarantee clean state isolation.
* Include **2-3 lines of explicit justification/delta** in the campaign master `README.md` explaining what changed between Commit `X` (`FL001`) and Commit `Y` (`FL002`) to justify running the new Friction Log.
### 4. Narrative Intent vs. Executed Mechanism (Semantic Drift Check)
* **Never accept `exit 0` as proof of success:** A command returning 0 only proves valid syntax, not that the author's educational goal was achieved.
* **The Semantic Drift Invariant:** Before certifying any step, contrast the **Narrative Promise** (what the title, prose, and diagrams claim to teach) with the **Executed Mechanism** (what the commands actually perform). If the commands take a degraded shortcut or bypass the promised architecture, flag a **P1 Semantic Drift Defect**.
* **Empirical State Verification:** Always formulate an assertion that queries the live platform state directly to prove architectural compliance, rather than relying on command exit codes.
### 5. The "Less is More" Sacred Covenant: High Friction for Codelab Edits
* **Every single line added to student-facing codelab text must be weighed with a heavy heart.**
* Never bloat the codelab with 10 lines of rare edge-case workarounds, compiler warnings, or esoteric shell fixes.
* **Hierarchy of Resolution:**
1. Fix it silently in application code, dependencies, or automated wrappers (`just recipes`, `npm test`, etc.).
2. Add unit/integration tests in the repository test suite.
3. Document the tribal knowledge in an **Agent Skill** (`skills/how-to-use-this-repo/references/`).
4. Only if 50%+ of all students will hit the issue, add a concise 1-line note to the codelab.
### 6. The Proactive Visual Mandate (Eliminate Bystander Effect on TODO Screenshots)
* Whenever the agent encounters a `> 📸 TODO(riccardo): add screenshot of ...` in the codelab, it is **strictly forbidden to ignore it or leave it as a TODO**.
* The agent has live credentials, headless Chrome (`google-chrome --headless`), local ports/proxies, and running services.
* The agent MUST proactively:
1. Trigger or render the relevant UI / terminal state.
2. Capture, crop, and save the image into `assets/images/` and the staging directory.
3. Replace the `TODO` with the markdown image tag and verify visual rendering.
### 7. Enforce IaC Single Source of Truth (No Terraform vs CLI Collisions)
* Infrastructure provisioned by Terraform (secrets, buckets, service accounts, databases) must **never be redundantly re-created via manual CLI commands**.
* Commands following Terraform steps must be **Pre-Flight Inspection Checklists** (e.g., `gcloud secrets describe <SECRET_NAME>`), not colliding creations (`gcloud secrets create`).
### 8. Empathize with Windows Users & Eliminate Environment Friction
* Assume 50% of students are non-expert Windows users who struggle with git, PowerShell paths, and shell environments.
* Keep copy-paste commands foolproof.
* Eliminate manual environment sourcing (`source .env`) by enforcing `set dotenv-load := true` in `justfile`.
* If an environment variable is missing (e.g., `GOOGLE_CLOUD_ACCOUNT`), scripts must output clear, actionable, copy-paste terminal remedies rather than failing with cryptic errors.
### 9. Tone Sobriety & Typography Restraint (No "Fake Wows" or AI Self-Talk)
* **Never use hyperbole or market-speak:** Eliminate fake enthusiastic claims like *"The WOW moment!"*, *"Amazing capability!"*, or celebratory commentary directed at the LLM itself.
* **Critique with empathy:** Before writing that something is a "wow moment", ask: *is this truly a wow moment for the human student, or is it an everyday occurrence / confusing technical step?*
* **Keep the tone sober, technical, and measured.**
* **Typography Rule:** Reserve **bold** strictly for technical entities (command flags, file paths, shell commands, environment variables, critical warning labels). Never bold emotive adjectives or artificial praise.
### 10. Strict TDD Mandate for Bug Fixes (Test-First Progression)
* **Every bug fix MUST be preceded by a failing automated test.** Never write a fix directly in the codebase without first demonstrating the failure in the test suite.
* **TDD Invariant:**
1. Write an automated unit, integration, or architecture test in the project's native test framework proving the defect.
2. Run the test suite and verify that the test **FAILS (RED)**.
3. Implement the minimal fix in application code or configuration.
4. Run the test suite and verify that the test **PASSES (GREEN)**.
5. Commit both test and fix together.
* **Cumulative Test Robustness:** Every FL iteration MUST leave the repository with strictly more automated tests than before (`tests_count(FL_{N}) > tests_count(FL_{N-1})`). This guarantees that regressions are permanently locked out.
### 11. Spec & Constitution Awareness + 160-Char Tweet Checkpoint
* If the repository contains `docs/CONSTITUTION.md` or `docs/SPEC.md` (or `workshop/SKELETON.md`), the FL agent MUST verify step compliance against them.
* At the conclusion of every Codelab page in `FRICTION_LOG/XX.md`, the agent MUST write a **160-character Tweet Checkpoint** answering:
`🐦 Constitution/Spec Tweet: [Yes/No + brief rationale <= 160 chars]`
### 12. Mandatory Kickoff Triad: Interactive Agreement Before Reproduction
* **The agent is STRICTLY FORBIDDEN from beginning codelab reproduction without agreeing on the Kickoff Triad with the user:**
1. **Tester Identity**: Inspect `gcloud auth list` and present selectable active identities (e.g. `ricc@google.com`, `rubycon.italy@gmail.com`).
2. **Billing Account**: Confirm the active Billing Account ID (e.g. 90-day sandbox pool `011F17-0F9CE4-E03264`).
3. **GCP Project ID**: Agree on whether the agent should autonomously create a fresh virgin project under that billing account (`<slug>-fl<NN>-<random>`) or use an explicit virgin project ID provided by the user.
* **No Assumption Rule**: Do NOT blindly recycle previous `.env` files or assume an expired project is valid. Lock the triad with the user first!
* Once the Kickoff Triad is agreed, the agent records it in `.env.fl` and executes autonomously without pausing between steps.
### 13. Skill Version & Machine-Readable Telemetry Tracking
* Telemetry format (`friction_log.yaml` / `friction_log.json`, `apiVersion: devrel.google.com/v2alpha1`) was introduced in skill **`v0.3.0`**.
* Explicit tracking of `environment.skill.name` and `environment.skill.version` is mandatory starting from **`v0.3.1`** / **`v0.3.2`**.
* Every Friction Log artifact (`.env.fl`, `README.md`, `FRICTION_LOG.md`, `friction_log.yaml`) must explicitly record the skill version.
### 14. Mandatory Pre-Teardown UAT Gate & Artifact Proof of Work
* **The agent is STRICTLY FORBIDDEN from tearing down cloud infrastructure (`terraform destroy`, unlinking billing, deleting projects) without interactive user UAT validation!**
* Before executing any destructive cleanup commands, the agent MUST:
1. **Generate a Proof of Work Artifact** (`gcp_resources_flXXX.md` / `proof_of_work.md`) containing:
- Screenshots of the running application / UI in action.
- Live Cloud Run service URLs and custom domain endpoints.
- The Hive Multi-Project Registry link showing service status 🟢 **UP**.
- Database instance details (Cloud SQL connection name, authorized IPs).
- Storage bucket URLs, BigQuery datasets, and Vertex AI / GenAI endpoints.
2. **Present the Artifact & Request Explicit UAT Validation**:
- Present the Proof of Work Artifact link to the user.
- Ask the user for validation: *"I have completed all reproduction steps and verified the environment. Here is the proof of work artifact. Do you validate the run and authorize infrastructure teardown?"*
3. **Wait for Human Confirmation**:
- Only after the user confirms UAT validation and explicitly approves teardown may the agent execute `terraform destroy` and unlink the billing account.
- If the user wishes to inspect the live app or test additional features first, the agent leaves the infrastructure running until instructed.
### 15. Multi-Instance Isolation & Collision Guard (`CHAT_ID`, `INCARNATION_ID` & `gcloud config`)
* **Dedicated Iteration Folder & Chat ID Locking**:
- Whenever multiple Friction Log instances might run concurrently (e.g. parallel agents or multiple sessions), each instance MUST operate in its own dedicated iteration folder (`<YYYYMMDD>-fl<NNN>`).
- The agent MUST stamp its unique session identifier (`CHAT_ID` or Antigravity `INCARNATION_ID` UUID) into `$FOLDER/.env.fl` immediately upon start.
- **Collision Guard**: If `$FOLDER/.env.fl` already exists with a different non-empty `CHAT_ID` / `INCARNATION_ID`, the agent MUST halt, warn, and ask the user rather than overwriting an active session!
* **Reentrant & Isolated `gcloud` Configuration**:
- To prevent concurrent gcloud commands in different terminals or agents from mutating each other's active project or account, the agent MUST define and activate an isolated named configuration:
```bash
export CLOUDSDK_ACTIVE_CONFIG_NAME="fl<NNN>-<SLUG>"
gcloud config configurations create "$CLOUDSDK_ACTIVE_CONFIG_NAME" 2>/dev/null || gcloud config configurations activate "$CLOUDSDK_ACTIVE_CONFIG_NAME"
```
* **"When in doubt, ask USER!"**:
- If there is any ambiguity about project state, folder ownership, or credential collisions, never guess — prompt the user interactively (`ask_question`).
## Core Workflow
When the user provides a Codelab URL, follow these exact steps. Ensure each step is fully completed before moving on to the next. Do not skip steps. This skill is designed to be resumable, so if the execution is interrupted, restart the skill and pick up where you left off.
### Step 0: Immediate `.env.fl` Creation & Collision Check (Atomic First Action)
Before fetching any content, scaffolding subdirectories, or enabling cloud APIs:
1. Ensure the iteration folder (`<YYYYMMDD>-fl<NNN>`) exists.
2. Check for collision: inspect `$FOLDER/.env.fl`. If an active session with a different `CHAT_ID` / `INCARNATION_ID` exists, stop and prompt the user.
3. Write `$FOLDER/.env.fl` immediately from `references/env.template`, recording:
- Verbatim User Prompt commented at the top (`# User Prompt: ...`)
- Unique `CHAT_ID` / `INCARNATION_ID`
- `FRICTIONLOG_SKILL_VERSION="0.3.5"`
- `CLOUDSDK_ACTIVE_CONFIG_NAME="fl<NNN>-<SLUG>"`
4. Activate the isolated `gcloud` named configuration (`CLOUDSDK_ACTIVE_CONFIG_NAME`).
### Step 1: Preparation & Dynamic Scaffold
1. Determine the base campaign directory (`b<BUG_ID>-<YYYYMMDD>-frictionlog-<CODELAB_SLUG>`) and iteration subdirectory (`<YYYYMMDD>-fl<NNN>`, e.g. `20260911-fl001`).
2. Ensure the Buganizer campaign issue is tagged with hotlist `#8950858`.
3. Run the included `scripts/setup_scaffold.sh` script passing the Codelab URL (or local `index.lab.md` path) as the second argument:
```bash
./scripts/setup_scaffold.sh <YYYYMMDD-frictionlog-CODELAB_TITLE> <CODELAB_URL_OR_MD_PATH> [BUG_ID]
```
This script automatically creates the directory structure AND invokes `scripts/extract_codelab.py`, which extracts every step (`01.md` .. `NN.md`) and **dynamically populates the Step-by-Step Scorecard Table in `README.md` with the exact `N` steps, real step titles, and durations**!
### Step 2: Download and Mirror Codelab Content (Dynamic Scorecard Sync)
1. If `setup_scaffold.sh` was called without `<CODELAB_URL>`, run `extract_codelab.py` directly:
```bash
python3 scripts/extract_codelab.py <URL_OR_MD_PATH> <YYYYMMDD-frictionlog-CODELAB_TITLE>/codelab/original
```
2. *Fallback for JS-rendered Codelabs*: If `extract_codelab.py` yields empty files (due to dynamic JS rendering), use `web_fetch` or `curl` to save each step into `codelab/original/01.md`, `02.md`, ..., `NN.md` (with `# Step Title` on line 1), and then run:
```bash
python3 scripts/extract_codelab.py --sync-readme <YYYYMMDD-frictionlog-CODELAB_TITLE>
```
This scans `codelab/original/*.md` and **dynamically replaces the placeholder Pagella Semaforica in `README.md` with the exact `N` steps and titles**!
3. Copy all the original markdown files into the `codelab/proposed/` directory. You will apply fixes and patches to the copies in this directory later.
### Step 3: GCP Project Setup & Mandatory Kickoff Triad Agreement
1. **Interactive Kickoff Agreement (Mandatory Stop)**:
The agent MUST present the Kickoff Triad options to the user and agree on:
* **1. Tester Identity**: Run `gcloud auth list` and present the available active identities (e.g. `ricc@google.com`, `rubycon.italy@gmail.com`). Ask the user which identity to use.
* **2. Billing Account ID**: Ask the user for the active Billing Account ID (or confirm the 90-day pool default, e.g. `011F17-0F9CE4-E03264`).
* **3. Virgin GCP Project ID**:
- *Option A (Recommended)*: Autonomous Project Creation — the agent creates a brand-new virgin project (e.g. `<codelab-slug>-fl<NN>-<random>`) and links it to the billing account.
- *Option B*: User provides a pre-created virgin project ID with billing already enabled.
* **Gatekeeper Invariant**: **DO NOT PROCEED to Step 4** until the user has explicitly confirmed the Identity, Billing Account, and Project ID plan.
2. If the user provides an existing `PROJECT_ID`:
* Verify that the project exists, has active billing associated (`gcloud beta billing projects describe <PROJECT_ID>`), and contains no pre-existing colliding resources.
* Save it to `.env.fl` and `friction_log.yaml` and proceed to Step 4.
3. If the user approves autonomous project creation:
* Use `gcloud` to create the project: `gcloud projects create <PROJECT_ID> --name="FL <SLUG>"`.
* Link billing: `gcloud beta billing projects link <PROJECT_ID> --billing-account=<BILLING_ACCOUNT_ID>`.
* Verify billing is active. **DO NOT PROCEED** until verified.
* Save configuration to `.env.fl` and `friction_log.yaml`.
4. **Autonomous Execution Mandate**: Once the Kickoff Triad is locked in `.env.fl`, execute all codelab pages autonomously without stopping between steps.
### Step 4: Autonomous Execution, Logging, and Repo Analysis (The 6-Question Step Audit)
Begin reproducing the codelab autonomously, going through each page (`01`, `02`, ..., `NN`) sequentially.
For each page `XX`:
1. Check if `FRICTION_LOG/XX.md` already exists and is complete. If it is, **skip** to the next page. This allows the workflow to be resumable.
2. **Execute the 6-Question Structural Audit**:
- **Q1: Prerequisite Integrity**: What was expected to be finished in Page `XX-1`? Is our environment and cloud state 100% prepared, or did we carry over half-baked state?
- **Q2: Teleological Purpose & Scope (Semantic Drift Check)**:
View on GitHub