Posts in category “Tips”

Excalidraw's hand-drawn look is free — Excalidraw+ only buys you cloud collab

I almost passed on the cute hand-drawn flowchart style, assuming it sat behind a subscription. It doesn't. The hand-drawn aesthetic is Excalidraw's default and only style, and it's completely free. The paid tier, Excalidraw+, is team cloud collaboration and version history — nothing to do with how the diagrams look.

mermaid.live is the same story: the official open-source editor for Mermaid.js, free, no credits, no pay-per-render. The "credit-based" impression usually comes from third-party SaaS tools that generate Mermaid from a prompt.

So going from a flowchart to a hand-drawn version costs nothing. Get your flowchart as Mermaid (write it, or hand a vision-capable AI a photo of your sketch), then paste it straight onto the Excalidraw canvas — it detects the syntax and pops a "Parse as Mermaid" import dialog. There is no Insert → Mermaid item in the hamburger menu or toolbar (those only have Open / Save / Export / Live Collaboration); the other entry point is the command palette (Ctrl/Cmd + /) → search Mermaid.

ECS force-new-deployment vs scaling desiredCount to 0 then 1

Need to restart an ECS service to pick up a changed SSM Parameter Store value (env vars/secrets are resolved when a task starts, so any fresh task picks up the new value). Two ways to force a restart look equivalent but aren't.

aws ecs update-service --force-new-deployment runs a normal rolling deployment, governed by the service's deploymentConfiguration:

aws ecs update-service --cluster my-cluster --service my-service --force-new-deployment

desiredCount never changes. If maximumPercent is above 100 (e.g. 200%), ECS starts the new task first, waits for it to pass the ALB health check, then drains and stops the old one — new and old run side by side for a moment, so there's effectively zero downtime.

Scaling desiredCount to 0 and back to 1 is a hard stop-then-start: every running task is killed first, the target group is empty until the new task comes up and passes health checks, and anything hitting the service in that window fails. It also completely bypasses the rolling-deployment logic — there's no overlap to make it graceful.

Same end state (new task, new config), different path to get there. Two things to check before relying on force-new-deployment for a "safe" restart: maximumPercent needs to allow >100%, or you get the same stop-then-start behavior with the failure mode you were trying to avoid; and deploymentCircuitBreaker — if it's disabled, a broken new task version just cycles and retries forever without rolling back, while the old task quietly keeps serving traffic, so the deployment looks non-disruptive but never actually finishes.

Three-agent caucus before opening a design ticket

A solo design pick ships a brittle ticket. A small jury forces you to surface the hard rule, spot when "labeling problem" is really a data gap, and converge to ready instead of refining.

When to convene

Caucus is for design questions with real divergence, where the goal is a ready ticket. Skip it for one-line facts (one agent), pure execution (just do it), or where there's only one sane option.

Composition: two advocates + one skeptic

Two advocates pick majority-wins and call it consensus. Add an impartial chair/skeptic whose job is failure modes and a decision criterion. Three is convention, not doctrine — two advocates + one chair works; one advocate + one skeptic works; three advocates doesn't.

The three prompts share one SCENARIO

Each agent gets the same verified facts (IDs, code-line refs, observed outcomes). Letting each agent self-research drifts the facts and you can't synthesize. Then each gets a distinct lens and a boundary:

SCENARIO (verified): ...
CONTEXT (read these files, these are the related issues, decision-maker's steer): ...
YOUR LENS: [extend-X | separate-track | skeptic/chair]
BOUNDARY: read-only, no code, ≤500 words, return VERDICT line.

Use VERDICT as the last line so synthesis can grep it. Pick lens names that frame the choice (extend-#122 advocate, separate-track advocate, skeptic/chair) — the framing shapes the output.

Run the three concurrently in background; wait for all three before synthesizing. Sequential loses the wall-clock and the parallel disagreement.

Synthesize

  1. Consensus → hard rule. Whatever all three agree on goes in as a non-negotiable constraint, not a soft preference.
  2. Divergence → chair's criterion + compatibility points. The skeptic's job is to name when each advocate breaks. Often the advocates are compatible once you apply the criterion (e.g. fallback rule + quarantine path, gated by data-first verification).
  3. Lock → ready. The whole point of the caucus is to converge. If you converged, open ready and release the lock. Don't re-refine.

Traps

  • Treating caucus as solution. Three agents return positions; you synthesize. Letting them agree with each other is a fragile consensus.
  • No skeptic. Two advocates ship majority-wins.
  • No shared SCENARIO. Facts diverge, synthesis collapses.
  • No VERDICT line. Agent writes an essay, you can't grep.
  • Caucus for execution. Locating a bug, writing a doc, picking a flag value — none of these need a jury.
  • "Three" as dogma. Two advocates + one chair is the minimum useful shape. Three advocates is the maximum useless shape.

The synthesis rule that matters most: when the chair says "this is a data problem disguised as a labeling problem," that's the reframe — verify the data first, then design the fallback. Without the skeptic, you'd have built a clever rule on top of an incomplete export and shipped proxy labels.

GitHub Pages cname says "must verify" but your domain is Verified? Check your other account

You're migrating a GitHub Pages site from your personal account to an org. You verify the custom domain for the org, the org's Pages settings show it green "Verified", and then binding it to the repo fails — over and over:

You must verify your domain app.example.com before being able to use it.

Every route is blocked. The API returns 400:

gh api -X PUT repos/<org>/<repo>/pages -f cname=app.example.com
# => "Invalid cname" / "You must verify your domain..."

The repo's Settings → Pages custom-domain box throws the same error. Switching to legacy "Deploy from a branch" with a CNAME file already in the branch? The cname stays null. You can't even unpublish to reset — DELETE /repos/<org>/<repo>/pages comes back 422 Deactivating GitHub Pages for this repository is not allowed.

The verified-domains list says green. The cname check says unverified. Both are telling the truth.

The domain is also verified under your personal account. It's a leftover from when the site lived there and pointed at <user>.github.io. That personal verified claim silently takes precedence and blocks the org repo from binding the cname. GitHub never says "this domain is claimed elsewhere" — just the generic must-verify error, which sends you down a rabbit hole of re-verifying on the org side that never helps.

Fix: remove the verified domain from the personal account (user Settings → Pages → verified domains → remove), then bind the cname on the org repo. It goes through immediately.

A tell that this is your problem: the custom domain used to resolve to <user>.github.io before the migration.

One related trap: apex-domain verification does not auto-cover subdomains for cname binding, despite the docs implying it does. app.example.com needs its own _gh-<org>-o.app.example.com TXT even when example.com is already verified — otherwise the same must-verify wall.

Vagrant Terminal always opens as Administrator? Turn UAC back on

On Windows, when you open Terminal in a Vagrant VM, it sometimes runs in Administrator mode regardless of which shell you choose — even when you explicitly selected normal user mode.

The fix is to restore User Account Control (UAC) prompts:

  1. Open Control Panel → System and Security
  2. Under "Security and Maintenance", click "Change User Account Control settings"
  3. Move the slider back to the default: "Notify me only when apps try to make changes to my computer"
  4. Click OK, then confirm with Yes

When UAC is fully disabled (slider at "Never notify"), Windows bypasses the elevation prompt and grants administrative privileges silently — which causes every Terminal session to launch as Administrator. Restoring UAC to its default level re-enables the elevation check and lets normal user sessions work normally again.