tooling
Technical notes on web development, DevOps, and AI integration.
64 articles
- 17:04tooling
All Unit Tests Green, Yet the Converter Still Broke
Three pull-side bugs slipped past unit tests that were green on each side; only the round-trip property test caught the unsynchronized two-sided contract.
TL;DR: A round-trip property test over real docs failed despite green unit tests, showing the push and pull sides followed different contracts. Fixes addressed nested bold links via a wrap stack, a regex stash leak fixed by looping, and empty quote markers needing canonicalization. The lesson is unit tests only prove local specs, so you need cross-boundary property tests.
#plane#python#markdown - 16:20tooling
Two-way converter: conservative on push, tolerant on pull
A horizontal rule that vanished without a trace exposed a healthy two-way converter design: canonical push, tolerant pull that still refuses loudly.
TL;DR: My horizontal rule vanished on pull because the parser only handled <hr /> and silently ignored plain <hr>. The fix now throws a clear error for the bare tag instead of quietly dropping it. The tool now pushes conservative canonical HTML but only tolerates its known dialect on pull, backed by round-trip property tests.
#plane#python#markdown - 15:26tooling
The Markdown converter I trust is the one that refuses
A two-way repo-to-Plane converter that rejects anything outside a closed subset, line number included, instead of guessing.
TL;DR: The doc-sync converter rejects unsupported Markdown with an exact line number instead of silently truncating content. It only handles a strict subset like headings to h4, lists, tables and code blocks while frontmatter stays repo-side and images become pointers. This strict grammar and repo-side normalization makes round-trip conversions predictable and errors easy to fix.
#plane#python#markdown - 14:17devops
The document mirror moved offices: work items to Plane Pages
The document mirror moved off the kanban board and into Plane Pages, and the storage contract forced a full identity redesign.
TL;DR: The mirror moved from Work Items to Pages, which preserves HTML comments instead of sanitizing them, forcing a new identity design. Pages are flat with no folders, need full replacement on update, and require archiving before delete with verify-after-write. Sync now trusts content hashes, allows two-way edits only for meeting notes, and keeps library docs one-way with divergence alerts.
#plane#self-hosting#git - 23:25devops
Done on the tracker is a claim; the proof lives in Git
A card flipped to Done with nothing behind it. Now a work item only counts as done when its evidence hashes actually resolve in the repository.
TL;DR: A Done label means nothing without Git proof, so I stopped trusting tracker status alone. I built a gate that only allows Done when visible evidence lines with commit hashes and tags actually resolve in the repo. Strict rules like WIP limits, date handling, and separating docs keep the board honest and verifiable.
#plane#self-hosting#git - 23:25devops
One-door Plane onboarding: logic in one repo, data in every repo
I almost copied a skill folder into every repository. The healthier shape turned out to be one onboarding door and tiny consumer footprints.
TL;DR: Instead of copying the skill to every repo, it stays centralized and consumers keep only light config and templates. This avoids maintenance debt since fixes happen once, while staying cheap because Claude Code only loads skill details when used. An offline helper handles scaffolding safely and idempotently, while online work runs through Plane's MCP tools.
#plane#self-hosting#claude-code - 14:26ai
Designing Init Rules Skill: Layered Pack and Idempotency
A 199-line spec for the init-rules skill: layered universal + per-stack packs, CLAUDE.md as an index, and idempotent re-runs the Go generated-code and Copier way.
TL;DR: Starting from a bloated root CLAUDE.md, the author split rules into on-demand, path-specific files instead of one massive doc. The fix became a layered, harness-first skill pack with universal, stack-specific, and scaffold layers plus assert-based self-checks. To make reruns safe, the generator owns all artifacts like Go's generated-code marker, enabling idempotent smart merges that preserve local changes.
#ai-agents#tooling#automation - 09:00security
The Mechanical Redaction Gate That Runs Before Publish
A 9,000-character silent truncation cut the redaction rules out of the writing prompt. The fix that mattered was a mechanical gate on the final artifact.
TL;DR: A style guide was silently truncated at 9,000 characters, cutting the redaction rules before they reached the writer model. The fix loads the guide whole and adds a mechanical verification gate, check_redaction, that scans the final article for non-documentation IPs and secret-like token prefixes. False positives cost minutes; published leaks are permanent, so the trade-off is easy.
#security#tooling#ci - 22:20tooling
When Browser Automation Selectors Break on Locale Switches
My automation browser profile leaked an id-ID locale, the UI rendered Tanya Qwen instead of Ask Qwen, and every exact-label selector quietly broke. Here is the two-layer fix.
TL;DR: An automation suite broke because the browser profile's id-ID locale made the target site render UI text in Indonesian, so exact-match selectors like "Ask Qwen" failed. The fix: regex alternation accepting both languages, plus pinning the locale via context emulation. A small assert-based test guards against regressions.
#automation#playwright#regex