~/blog/building-wakii-in-the-open-log-4
build log #build-log#wakii#evidence Wakii team 7 min read

Building Wakii in the open — log #4

Building Wakii in the open — log #4

Log #3 covered the frame: FI-349 rebuilt the blog and closed as PR #2. This log covers what sits inside the frame — the twenty longform posts of story FI-359, each in a VI and an EN version. The interesting part is not the number twenty. It is the editorial framework built alongside them to keep those twenty posts honest: a matrix locked before writing began, a word-counting lint that accepts no excuses, and a forbidden list that ships with the build. The story closed as PR #3 — and the work did not end there: after the merge came an integration pass worth its own detail.

TL;DR:

  • 20 topics had their slug, publish date, and category locked in a matrix before the first line was written; split as 3 tutorial / 13 tech / 4 build-log.
  • The word band is a build condition, not a suggestion: VI 900-1400 (failing at 1470), EN floor 800 — text inside fenced code blocks never counts.
  • The claims registry is the single source of truth for forbidden phrases: the lint reads the registry at run time instead of copying the list into the script.
  • PR #3 merged at 00:32 UTC on 2026-09-08; after the merge the build chain gained one gate — and the lesson is that a green build must be proven on the merged result before calling the work done.

Twenty topics, one matrix locked before writing

FI-359’s earliest decision was not “what to write” but “lock everything first”: twenty topics, each with a fixed slug, publish date, and category in a matrix table, committed to the repo before the first post was opened. Counting the split by category is one grep over that very table:

$ grep -o '| tutorial |\|| tech |\|| build-log |' \
    docs/superpowers/editorial/2026-blog-longform/topic-matrix.md \
  | sort | uniq -c
   4 | build-log |
  13 | tech |
   3 | tutorial |

Source: grep on topic-matrix.md, public repo wakii-dev/wakii-site, run 2026-09-08.

Four plus thirteen plus three equals twenty — matching the matrix row count. Writing against a matrix locks away the decisions most prone to drifting: no post moves its own publish date, no slug changes mid-flight on a whim. The price of that rigidity buys something repeatable: anyone who opens the matrix knows exactly what the blog will contain, before the blog contains it.

The word-band lint: a counting algorithm with nothing to please

Every long post risks one disease: padding to hit a length. This series’ lint blocks that disease with a public counting algorithm, named D1 in the style guide: take the body after the frontmatter, strip every fenced code block, then count the words of what remains. Stripping fenced blocks is the pivotal choice — an ASCII diagram or a command transcript must not count toward the band, or every post would reach “900 words” through pictures. The constants sit right in the script:

/* scripts/check-blog-content.mjs — word band, decision D1 */
const VI_MIN = 900;
const VI_WARN = 1400;
const VI_HARD = 1470;
const EN_MIN = 800;

Source: scripts/check-blog-content.mjs, public repo wakii-dev/wakii-site, retrieved 2026-09-08.

VI under 900 words fails; over 1400 earns a warning; over 1470 — the hard cap — fails. The EN floor is 800. The VI and EN versions of each post share structure, date, and category; a length difference between the two languages is accepted, while a missing half of a locale pair is not — the parity gate upstream of this one already takes care of that.

The claims registry: a forbidden list that ships with the build

Sourced numbers are one half of “not lying”. The other half is product phrases that must never appear in a post. Rather than relying on writers’ memories, the story built a claims registry: a markdown file with an ALLOWED section — what has been verified, with sources — and a FORBIDDEN section, one literal phrase per line. The lint reads exactly that FORBIDDEN section at run time and greps the whole file, title and description included, case-insensitively. The comment in the script is a manifesto on its own:

/* The forbidden list is parsed from the registry at run time — the registry
   is the single source of truth, the script never duplicates it. */

Source: scripts/check-blog-content.mjs, public repo wakii-dev/wakii-site, retrieved 2026-09-08.

That means an unverified claim needs no one to “remember” to avoid it: it lives in the registry once, and every post after it gets blocked at build time automatically. The post done means evidence dissected this principle at the story layer; the registry and the evidence pack — snapshots of numbers with their source commands and retrieval dates — are that same principle’s version for prose.

PR #3 and the integration pass after the merge

FI-359 closed in the series’ exact shape: converged onto one branch, one PR. The PR transcript, run on the very day this log was written:

$ gh pr view 3 --repo wakii-dev/wakii-site --json state,mergedAt,title
{"mergedAt":"2026-09-08T00:32:26Z","state":"MERGED","title":"FI-359: Blog longform — 20 bài viết dài làm nổi bật tính năng Wakii (30 posts en/vi)"}

Source: gh pr view, public repo wakii-dev/wakii-site, run 2026-09-08.

A green merge is not the finish line. Right after the merge came the integration pass on the destination branch: when FI-349’s new blog surface met 40 new post files, the build chain needed one more check in front of astro build. The post-integration build line is four commands chained with && — one red command stops the whole chain:

"build": "node scripts/check-blog-slug-parity.mjs && node scripts/check-blog-utils.mjs && node scripts/check-blog-content.mjs && astro build",

Source: package.json, public repo wakii-dev/wakii-site, retrieved 2026-09-08.

Log #2 captured the three-command build line; it is four now, and that difference is the sourced trace of a real integration pass: the new utility gate was wired in after the two stories met, not before. The operational lesson lives exactly there — a clean merge on a story branch proves nothing about integration; the green build must be proven on the merged result before the work is called done.

Keeping log #2’s promise, with a fresh snapshot

Log #2 ended with a promise: the numbers would be captured again and compared — which moved, which held still. At the 2026-09-08 snapshot, here is the result:

NumberLog #2 (2026-09-07)Snapshot 2026-09-08Status
Desktop releasesv1.4.199 + v1.4.198, both on 2026-09-05re-verified: IDENTICALheld still
Androidmobile-android-v0.0.48 (Pre-release)IDENTICALheld still
Blog10 → 30 posts (the plan)25 slugs × 2 locales = 50 fileslanded
Next plan+44 slugs → 69 × 2 = 138 pagespublic in the matrix

Source: FI-359 evidence pack, §Numbers snapshot (rows 2+7), captured and re-verified 2026-09-08; topic-matrix-batch2.md committed in the repo, retrieved 2026-09-08.

The kit’s numbers — 20 total / 13 public skills and 24 story-* CLIs — were captured with their source commands in log #2; the 2026-09-08 re-verification returned them unchanged, so this log does not republish that table. As for 138: it is the public plan sitting in the matrix committed to the repo — a list of topics, not a work-in-progress state. This log series only tells what has closed, and promises to tell what closes next — the series continues.

To build a similar editorial framework for your own project, the getting started page is the entry point: install the kit, open the Superpowers panel, and run the first story of your own.

Wakii is an agentic IDE with a built-in superpowers team.

get wakii ← all posts